Compare commits
488 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
4358d071b3 | ||
![]() |
e7aad7ee6c | ||
![]() |
6623f957a1 | ||
![]() |
335951b7e6 | ||
![]() |
9299eac552 | ||
![]() |
aed5b9d16e | ||
![]() |
2d6f6f6848 | ||
![]() |
36626f2d76 | ||
![]() |
9fab5451f5 | ||
![]() |
79670657a4 | ||
![]() |
441d89767d | ||
![]() |
43ea446b2a | ||
![]() |
63692b557c | ||
![]() |
31b303b9fd | ||
![]() |
0c067e26c8 | ||
![]() |
3810b487cd | ||
![]() |
d9a41840ce | ||
![]() |
f52c93c925 | ||
![]() |
cfe5086b10 | ||
![]() |
87dc97c8ea | ||
![]() |
023772d929 | ||
![]() |
f49137b833 | ||
![]() |
d6fe858e84 | ||
![]() |
15f03c0527 | ||
![]() |
51d340d95b | ||
![]() |
8cda91a6e6 | ||
![]() |
b99d6a51a6 | ||
![]() |
15ee059d30 | ||
![]() |
821d85e395 | ||
![]() |
be1344f63e | ||
![]() |
20bd030e78 | ||
![]() |
59cb5eab67 | ||
![]() |
6dac81e809 | ||
![]() |
1bb34caaa7 | ||
![]() |
c3aff98094 | ||
![]() |
0408b391da | ||
![]() |
b20a2d24e4 | ||
![]() |
3949529c32 | ||
![]() |
482c613ca6 | ||
![]() |
8ff3f04c0b | ||
![]() |
9ddb44c3dc | ||
![]() |
ca3643deef | ||
![]() |
b636ea0554 | ||
![]() |
f68b1cc8ca | ||
![]() |
91476d2701 | ||
![]() |
44948226bb | ||
![]() |
5b8f12fa94 | ||
![]() |
18d4962ef9 | ||
![]() |
307f3229d2 | ||
![]() |
ce544019eb | ||
![]() |
1784358fc2 | ||
![]() |
6497f6bf90 | ||
![]() |
b4e1b5aeca | ||
![]() |
ffba7ebf1b | ||
![]() |
761d044957 | ||
![]() |
307aaee082 | ||
![]() |
b1f6528605 | ||
![]() |
388d0eafa0 | ||
![]() |
f7ab52fec1 | ||
![]() |
f63d8080a3 | ||
![]() |
470bc6d545 | ||
![]() |
bc34bb5fa0 | ||
![]() |
1d9ac19c16 | ||
![]() |
ef1ec46bad | ||
![]() |
efd61fb376 | ||
![]() |
299d8b637a | ||
![]() |
086f685780 | ||
![]() |
4d97c1473b | ||
![]() |
63c435c610 | ||
![]() |
08e09c5d08 | ||
![]() |
a9b7531ab1 | ||
![]() |
224900890b | ||
![]() |
4800a79643 | ||
![]() |
c776da96ae | ||
![]() |
0eb84f5f76 | ||
![]() |
bb0243df47 | ||
![]() |
3dd26b8259 | ||
![]() |
fc2119ad5a | ||
![]() |
fe535c061e | ||
![]() |
75a8db833b | ||
![]() |
11a12bb48b | ||
![]() |
5b44df24ab | ||
![]() |
c95cde5cde | ||
![]() |
59ed6e51c1 | ||
![]() |
06bfaf709c | ||
![]() |
5f422e1b83 | ||
![]() |
7701671c7e | ||
![]() |
0ec3660e1a | ||
![]() |
f17f5da822 | ||
![]() |
ca3e31580f | ||
![]() |
4509b11816 | ||
![]() |
7fb7c23fb0 | ||
![]() |
4a5a002dc1 | ||
![]() |
3b893e7ccf | ||
![]() |
1d2e2ebdc7 | ||
![]() |
f70f82f896 | ||
![]() |
ba75d09cbf | ||
![]() |
44dee3929b | ||
![]() |
36b7842085 | ||
![]() |
ad9e33d0d7 | ||
![]() |
4ae54d736f | ||
![]() |
d7ed67a842 | ||
![]() |
d7a36c61b2 | ||
![]() |
3cba1c60f8 | ||
![]() |
1a8f883b63 | ||
![]() |
3ea5b4e010 | ||
![]() |
322bfed972 | ||
![]() |
a5b48c4730 | ||
![]() |
869bd1e0ef | ||
![]() |
a16c76940f | ||
![]() |
d382ca1613 | ||
![]() |
6cf1cc0fe9 | ||
![]() |
de911a0e3e | ||
![]() |
84f94ed564 | ||
![]() |
a6a729a065 | ||
![]() |
9124b2ddbd | ||
![]() |
d10df843cb | ||
![]() |
f2a714cece | ||
![]() |
d6573b9bfd | ||
![]() |
415a7ed2da | ||
![]() |
2073aa632d | ||
![]() |
825b27df57 | ||
![]() |
336b0c9799 | ||
![]() |
d48c1af824 | ||
![]() |
8c9c70ef3f | ||
![]() |
201aff6c0a | ||
![]() |
309cfa0514 | ||
![]() |
c39d6b18b2 | ||
![]() |
d9d776e5da | ||
![]() |
7f8017de76 | ||
![]() |
c3420b1684 | ||
![]() |
20f0e1dfc2 | ||
![]() |
ac5fa6c25c | ||
![]() |
1011e2dcc4 | ||
![]() |
b2d73eeda0 | ||
![]() |
25b2d06572 | ||
![]() |
3b1b6e9b7e | ||
![]() |
e9fec445ff | ||
![]() |
a9619be8d0 | ||
![]() |
f1a3126758 | ||
![]() |
49904b22bf | ||
![]() |
fc49c6490f | ||
![]() |
f00f5addfe | ||
![]() |
9cd25034fc | ||
![]() |
8935dd6482 | ||
![]() |
da4693b310 | ||
![]() |
302ef9227a | ||
![]() |
411441e1a8 | ||
![]() |
cfd370eb6d | ||
![]() |
1d2548a174 | ||
![]() |
16ca760901 | ||
![]() |
636d4e259e | ||
![]() |
5305ae7803 | ||
![]() |
8e212889a4 | ||
![]() |
1086dd85a4 | ||
![]() |
ca0fae7bdb | ||
![]() |
2229586b58 | ||
![]() |
c8e82ca57b | ||
![]() |
fc575a9554 | ||
![]() |
485aeedbf1 | ||
![]() |
24f1319007 | ||
![]() |
82887c013b | ||
![]() |
aefa5ba1c8 | ||
![]() |
17ab473576 | ||
![]() |
459069c5ee | ||
![]() |
d905171fcb | ||
![]() |
a0268f1c47 | ||
![]() |
b25ce96efb | ||
![]() |
e78bd37da0 | ||
![]() |
371a37df7a | ||
![]() |
af5d28e2a5 | ||
![]() |
8c2289ed74 | ||
![]() |
60359a19ba | ||
![]() |
faf9950562 | ||
![]() |
040bcf2fa0 | ||
![]() |
495981cb5a | ||
![]() |
128015f0fa | ||
![]() |
d491271e7a | ||
![]() |
1e9c6c5838 | ||
![]() |
b8946d8666 | ||
![]() |
a4c2fa2bc9 | ||
![]() |
fbdb3f12a1 | ||
![]() |
01fc633303 | ||
![]() |
8da3e8cb67 | ||
![]() |
bb6d99cb74 | ||
![]() |
f6c8eecb87 | ||
![]() |
f1de845554 | ||
![]() |
308d1775bf | ||
![]() |
ef5c063b09 | ||
![]() |
29e9ed6e4a | ||
![]() |
33cc108900 | ||
![]() |
0b173fb428 | ||
![]() |
9b193c74dd | ||
![]() |
663e2370a2 | ||
![]() |
b7a765bd8c | ||
![]() |
f79d7d5380 | ||
![]() |
6b45719e79 | ||
![]() |
fd6e8bd51e | ||
![]() |
704548343b | ||
![]() |
4657b3419b | ||
![]() |
3522dfe4c7 | ||
![]() |
7283f6e887 | ||
![]() |
1d2e453fc2 | ||
![]() |
e8efc743b2 | ||
![]() |
a5e276d50e | ||
![]() |
0ffb7ccb65 | ||
![]() |
9d383600bc | ||
![]() |
62358aec4e | ||
![]() |
c1a2c34a06 | ||
![]() |
aedf7c9a22 | ||
![]() |
58917d0b3e | ||
![]() |
9420231b58 | ||
![]() |
bd11bd2657 | ||
![]() |
e6a545309f | ||
![]() |
630ebc6b88 | ||
![]() |
036fe6f47f | ||
![]() |
f9735bdd35 | ||
![]() |
57577c95b4 | ||
![]() |
4351c8b678 | ||
![]() |
985a4e94cb | ||
![]() |
bcd69b4582 | ||
![]() |
e180704dd1 | ||
![]() |
4b3ee928ff | ||
![]() |
c8c3bff636 | ||
![]() |
a7ef7eb17d | ||
![]() |
eeed88aba8 | ||
![]() |
e90479e452 | ||
![]() |
826be5ce5b | ||
![]() |
d7ca83ef97 | ||
![]() |
4449353f3a | ||
![]() |
a077092631 | ||
![]() |
ff2d0b794e | ||
![]() |
cfdfaf2fb1 | ||
![]() |
d75fe2f428 | ||
![]() |
8fa42c9f30 | ||
![]() |
e1dbbb21ee | ||
![]() |
65f777baae | ||
![]() |
9cd65a3f02 | ||
![]() |
7cdf9c6c93 | ||
![]() |
360a70f3d8 | ||
![]() |
119a7fdebb | ||
![]() |
6263f163f9 | ||
![]() |
5ae631ee4f | ||
![]() |
9f165580e5 | ||
![]() |
218ce1c785 | ||
![]() |
fd8dbb10a5 | ||
![]() |
2c16379ec1 | ||
![]() |
a4695681b5 | ||
![]() |
2c041bbe14 | ||
![]() |
0919202599 | ||
![]() |
ca26da77c7 | ||
![]() |
bc2d5088c5 | ||
![]() |
8b4477bc8d | ||
![]() |
64a241c1f9 | ||
![]() |
fb8138a69d | ||
![]() |
e2c07edd7d | ||
![]() |
6455cb371f | ||
![]() |
7de05a841f | ||
![]() |
0cfa02b4ce | ||
![]() |
de1c2e7b57 | ||
![]() |
d8dcad4991 | ||
![]() |
b343134c01 | ||
![]() |
fbc9b53b6c | ||
![]() |
93e39165c2 | ||
![]() |
f923eef868 | ||
![]() |
0547066b30 | ||
![]() |
573106ae65 | ||
![]() |
9bbdbfecfb | ||
![]() |
b2efd238c4 | ||
![]() |
ba3f03c7ce | ||
![]() |
ec1ce2df83 | ||
![]() |
d06f7e4933 | ||
![]() |
1644ae706a | ||
![]() |
7d65dcc7ef | ||
![]() |
3f02e0077c | ||
![]() |
771d013087 | ||
![]() |
843f66575f | ||
![]() |
56f819b905 | ||
![]() |
7ae7ad92f8 | ||
![]() |
9f6c8dc21d | ||
![]() |
c0beaeb2b0 | ||
![]() |
b26ebb3150 | ||
![]() |
329079567e | ||
![]() |
0042c3bbe4 | ||
![]() |
6b848b1446 | ||
![]() |
8eb92ef7c6 | ||
![]() |
8fe523cacf | ||
![]() |
8745591f97 | ||
![]() |
a3ba6257ba | ||
![]() |
a9c0df015c | ||
![]() |
f74c188d5b | ||
![]() |
195eeb06b6 | ||
![]() |
9260b967b3 | ||
![]() |
ec63b6e58e | ||
![]() |
7835392d95 | ||
![]() |
265a35a903 | ||
![]() |
e51f2aaf61 | ||
![]() |
f8fcaa6d1f | ||
![]() |
977d2ddd18 | ||
![]() |
c32bfc1c8a | ||
![]() |
48b163fd6c | ||
![]() |
5fd58514b5 | ||
![]() |
8c78a00f2a | ||
![]() |
e5dd05e701 | ||
![]() |
d11bb52038 | ||
![]() |
3909202958 | ||
![]() |
e795b65df1 | ||
![]() |
dba8e2ebb8 | ||
![]() |
6216892594 | ||
![]() |
b89b03d314 | ||
![]() |
1da57a9478 | ||
![]() |
5781c23f0e | ||
![]() |
450213ae66 | ||
![]() |
8245eebabc | ||
![]() |
519ed7e8c7 | ||
![]() |
bd7d2770a2 | ||
![]() |
29fa7744e1 | ||
![]() |
c3ec17e1e8 | ||
![]() |
5289567773 | ||
![]() |
e978cb9914 | ||
![]() |
7a91013bd4 | ||
![]() |
c468e53fad | ||
![]() |
e146976af5 | ||
![]() |
7d81fa6247 | ||
![]() |
1a75d63ba1 | ||
![]() |
3b2a851f4f | ||
![]() |
64cd6ac98c | ||
![]() |
30f70b35a2 | ||
![]() |
c4b12f95e9 | ||
![]() |
41f8fd9550 | ||
![]() |
3c8261f286 | ||
![]() |
ee56002e1a | ||
![]() |
a5ec206a08 | ||
![]() |
f0e614fa2a | ||
![]() |
ca3b6cbb63 | ||
![]() |
d42c25bf56 | ||
![]() |
e1b4a1b9b8 | ||
![]() |
6e6102d125 | ||
![]() |
c3f135f532 | ||
![]() |
a088b81366 | ||
![]() |
fe26ba7305 | ||
![]() |
562aae8c92 | ||
![]() |
b8516c423e | ||
![]() |
47deda23e5 | ||
![]() |
3a87bf303c | ||
![]() |
c0ae772981 | ||
![]() |
314d4de816 | ||
![]() |
11a8e50d2e | ||
![]() |
a34825a692 | ||
![]() |
e6ef07139d | ||
![]() |
8516523efa | ||
![]() |
eb122a99f2 | ||
![]() |
45aaac4189 | ||
![]() |
f00a11da0e | ||
![]() |
b72d142a81 | ||
![]() |
0257bf4e85 | ||
![]() |
59f8e8c696 | ||
![]() |
1f79a19943 | ||
![]() |
69dd7a6855 | ||
![]() |
a49c7cb40c | ||
![]() |
1d08c22d1d | ||
![]() |
8a03a7b16b | ||
![]() |
10f7e2688e | ||
![]() |
3cb42a8b60 | ||
![]() |
5ed1f6d958 | ||
![]() |
ac1ca07e64 | ||
![]() |
a0800509cb | ||
![]() |
5e9cd13206 | ||
![]() |
e6b2afa1dc | ||
![]() |
c817b5d72d | ||
![]() |
bfa24facf9 | ||
![]() |
540bb95291 | ||
![]() |
925574e286 | ||
![]() |
4a79f3194e | ||
![]() |
f41f54cc60 | ||
![]() |
5d7550b43f | ||
![]() |
3d20917710 | ||
![]() |
86d22b5e9a | ||
![]() |
91f1da67f0 | ||
![]() |
a74ade90ba | ||
![]() |
ca4309c131 | ||
![]() |
ae16fd6d6a | ||
![]() |
bdc99bd887 | ||
![]() |
974ef9f77e | ||
![]() |
db2bae420f | ||
![]() |
c2d50c3b33 | ||
![]() |
b69cbcfe65 | ||
![]() |
ecb99f8f66 | ||
![]() |
8bff4f857b | ||
![]() |
094393e7fb | ||
![]() |
831a38a317 | ||
![]() |
5bcfd40a34 | ||
![]() |
8e5a6db764 | ||
![]() |
2a600e29ae | ||
![]() |
8e1812c1d6 | ||
![]() |
409255dd5c | ||
![]() |
a0483865bd | ||
![]() |
3cc927c0b5 | ||
![]() |
4a31504593 | ||
![]() |
9b7ca02f00 | ||
![]() |
ee1526fa11 | ||
![]() |
8e29ffc5a6 | ||
![]() |
18ec685902 | ||
![]() |
871bd680b8 | ||
![]() |
a591f86636 | ||
![]() |
f12f95bce7 | ||
![]() |
94fe7d245c | ||
![]() |
16a48cd2aa | ||
![]() |
699a4bda95 | ||
![]() |
9e8337efcb | ||
![]() |
aacbd6780c | ||
![]() |
eb0c77cea8 | ||
![]() |
7c717ec61c | ||
![]() |
81756c2587 | ||
![]() |
7ca842e712 | ||
![]() |
2304b64d9a | ||
![]() |
0e3f6c98aa | ||
![]() |
78980a993f | ||
![]() |
1317fd9e42 | ||
![]() |
2987812622 | ||
![]() |
fde21b4c98 | ||
![]() |
a62e04a4e4 | ||
![]() |
e947abcab2 | ||
![]() |
8f4908b1b7 | ||
![]() |
abb28548f1 | ||
![]() |
acb0c08ab4 | ||
![]() |
a9d76b1cfd | ||
![]() |
df257ead7a | ||
![]() |
7ee787951b | ||
![]() |
8b7632d964 | ||
![]() |
a57c063e6b | ||
![]() |
daff0fc566 | ||
![]() |
472dead0d6 | ||
![]() |
e948472475 | ||
![]() |
2e1af401c1 | ||
![]() |
70208d2157 | ||
![]() |
db828e7285 | ||
![]() |
d55a6b1944 | ||
![]() |
ed5a968d11 | ||
![]() |
b6e45c443c | ||
![]() |
6516f7047a | ||
![]() |
81662b8e17 | ||
![]() |
4aa2f65ec3 | ||
![]() |
e08d173e78 | ||
![]() |
23cb226196 | ||
![]() |
4645427403 | ||
![]() |
16a7391372 | ||
![]() |
ab26a20dde | ||
![]() |
4041955296 | ||
![]() |
3c210d388d | ||
![]() |
f8ab81e27d | ||
![]() |
70677e3a3a | ||
![]() |
5053daedb5 | ||
![]() |
e909feb693 | ||
![]() |
27f29fc0fa | ||
![]() |
bd2eec9a28 | ||
![]() |
d02d6e78ae | ||
![]() |
8b8d73c3b2 | ||
![]() |
ffd2aefc26 | ||
![]() |
1149497e56 | ||
![]() |
a2743376f8 | ||
![]() |
84cce98110 | ||
![]() |
3edff8f6fc | ||
![]() |
5d18b36083 | ||
![]() |
2dbe7268e4 | ||
![]() |
49291de381 | ||
![]() |
89bfa9c9d8 | ||
![]() |
e4b2c2ad6b | ||
![]() |
34eed0cb79 | ||
![]() |
86cf2981c1 | ||
![]() |
b69850cb21 | ||
![]() |
825198fb5a | ||
![]() |
47afdd2f19 | ||
![]() |
63a30a1e57 | ||
![]() |
7537286d3a | ||
![]() |
8dbd4be6ce | ||
![]() |
afd595c965 | ||
![]() |
d41a68c63e | ||
![]() |
5a3259b891 | ||
![]() |
12372b5071 | ||
![]() |
dc0737e803 | ||
![]() |
3a53ddbc59 | ||
![]() |
748b21117a | ||
![]() |
6d46f8a6cc | ||
![]() |
8cbbcc66be | ||
![]() |
822b4393c3 | ||
![]() |
4c20cb8969 | ||
![]() |
417f944b4d |
473 changed files with 22196 additions and 31306 deletions
|
@ -1,5 +1,5 @@
|
|||
### --- App Settings --- ###
|
||||
APP_NAME=Controlpanel.gg
|
||||
APP_NAME=Ctrlpanel.gg
|
||||
APP_ENV=production
|
||||
APP_KEY=
|
||||
APP_DEBUG=false
|
||||
|
|
38
.github/ISSUE_TEMPLATE/---bug-report.md
vendored
38
.github/ISSUE_TEMPLATE/---bug-report.md
vendored
|
@ -1,38 +0,0 @@
|
|||
---
|
||||
name: "\U0001F41B Bug report"
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: RamonRobben, AVMG20
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug 🐛**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
- OS: [e.g. iOS]
|
||||
- Browser [e.g. chrome, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Smartphone (please complete the following information):**
|
||||
- Device: [e.g. iPhone6]
|
||||
- OS: [e.g. iOS8.1]
|
||||
- Browser [e.g. stock browser, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
31
.github/ISSUE_TEMPLATE/---feature-request.md
vendored
31
.github/ISSUE_TEMPLATE/---feature-request.md
vendored
|
@ -1,31 +0,0 @@
|
|||
---
|
||||
name: "\U0001F680 Feature request"
|
||||
about: Suggest a feature or idea for this project
|
||||
title: "[feature] "
|
||||
labels: enhancement
|
||||
assignees: RamonRobben, AVMG20
|
||||
|
||||
---
|
||||
|
||||
# 🚀 Feature Request
|
||||
|
||||
### Is your proposal related to a problem?
|
||||
|
||||
*Provide a clear and concise description of what the problem is.
|
||||
For example, "I can't change x and it makes me have to do manual work"*
|
||||
|
||||
(Write your answer here.)
|
||||
|
||||
### Describe the solution you'd like
|
||||
|
||||
*Provide a clear and concise description of what you want to happen.
|
||||
For Example, "Automate the changing of x so I don't have to do it manually"*
|
||||
|
||||
(Describe your proposed solution here.)
|
||||
|
||||
### Additional context
|
||||
|
||||
*Is there anything else you can add about the proposal?
|
||||
You might want to link to related issues here, if you haven't already.*
|
||||
|
||||
(Write your answer here.)
|
43
.github/ISSUE_TEMPLATE/bug.yml
vendored
Normal file
43
.github/ISSUE_TEMPLATE/bug.yml
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
name: "\U0001F41B Bug report"
|
||||
description: Create a report to help us improve
|
||||
title: "[Bug]: "
|
||||
labels: ["bug"]
|
||||
body:
|
||||
- type: textarea
|
||||
id: what-happened
|
||||
attributes:
|
||||
label: What is your request about?
|
||||
description: |
|
||||
Provide a clear description of what the problem is.
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: version
|
||||
attributes:
|
||||
label: Branch
|
||||
description: What branch are you on?
|
||||
multiple: false
|
||||
options:
|
||||
- "main"
|
||||
- "development"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: solution
|
||||
attributes:
|
||||
label: Solution idea
|
||||
description: |
|
||||
Provide a clear description of how you want this bug to be fixed (Optional)
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: ctrlpanel-logs
|
||||
attributes:
|
||||
label: Ctrlpanel Logs
|
||||
description: Please copy and paste your laravel-log output. You may also provide a link to it using the following command `tail -n 100 /var/www/controlpanel/storage/logs/laravel.log | nc pteropaste.com 99`
|
||||
render: Shell
|
||||
- type: textarea
|
||||
id: additional-info
|
||||
attributes:
|
||||
label: Additional Info
|
||||
description: Anything else that could be used to narrow down the issue, like your config.
|
24
.github/ISSUE_TEMPLATE/feature.yml
vendored
Normal file
24
.github/ISSUE_TEMPLATE/feature.yml
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
name: "\U0001F680 Feature request"
|
||||
description: Suggest a feature or idea for this project
|
||||
title: "[Feature] "
|
||||
labels: ["feature"]
|
||||
body:
|
||||
- type: textarea
|
||||
id: feature-description
|
||||
attributes:
|
||||
label: Feature Description
|
||||
description: Provide a clear description of what your idea is all about, what it tries to solve and why it should be implemented.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: solution
|
||||
attributes:
|
||||
label: Solution Idea
|
||||
description: Provide a clear description how the idea should be implemented and why.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: additional-info
|
||||
attributes:
|
||||
label: Additional Info
|
||||
description: Anything else that could be used to implement your idea.
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2021 ControlPanel.gg
|
||||
Copyright (c) 2021 CtrlPanel.gg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
46
README.md
46
README.md
|
@ -3,55 +3,65 @@
|
|||
- PayPal Integration
|
||||
- Stripe Integration
|
||||
- Referral System
|
||||
- Partner System
|
||||
- Ticket System
|
||||
- Upgrade/Downgrade Server Ressources
|
||||
- Upgrade/Downgrade Server Resources
|
||||
- Store (credit system with hourly billing and invoices)
|
||||
- Email Verification
|
||||
- Audit Log
|
||||
- Admin Dashboard
|
||||
- User/Server Management
|
||||
- Customizable server plans
|
||||
- Customisable server plans
|
||||
- Vouchers
|
||||
- Alert System
|
||||
- Theme Support
|
||||
- and so much more!
|
||||
|
||||
# ControlPanel-gg
|
||||
# CtrlPanel-gg
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||

|
||||

|
||||
   [](https://crowdin.com/project/controlpanelgg)   
|
||||

|
||||

|
||||
   [](https://crowdin.com/project/controlpanelgg)   
|
||||
## About
|
||||
|
||||
ControlPanel's Dashboard is a dashboard application designed to offer clients a management tool to manage their pterodactyl servers. This dashboard comes with a credit-based billing solution that credits users hourly for each server they have and suspends them if they run out of credits.
|
||||
CtrlPanel's Dashboard is a dashboard application designed to offer clients a management tool to manage their pterodactyl servers. This dashboard comes with a credit-based billing solution that credits users hourly for each server they have and suspends them if they run out of credits.
|
||||
|
||||
This dashboard offers an easy to use and free billing solution for all starting and experienced hosting providers. This dashboard has many customization options and added discord 0auth verification to offer a solid link between your discord server and your dashboard. You can check our Demo here ([Demo](https://demo.controlpanel.gg "Demo"))
|
||||
This dashboard offers an easy to use and free billing solution for all starting and experienced hosting providers. This dashboard has many customisation options and added discord Oauth verification to offer a solid link between your discord server and your dashboard. You can check our [Demo here](https://demo.ctrlpanel.gg "Demo").
|
||||
|
||||
### [Installation](https://controlpanel.gg/docs/intro "Installation")
|
||||
### [Installation](https://ctrlpanel.gg/docs/intro "Installation")
|
||||
|
||||
### [Updating](https://controlpanel.gg/docs/Installation/updating "Updating")
|
||||
### [Updating](https://ctrlpanel.gg/docs/Installation/updating "Updating")
|
||||
|
||||
### [Discord](https://discord.gg/4Y6HjD2uyU "discord")
|
||||
### [Discord](https://discord.gg/4Y6HjD2uyU "Discord")
|
||||
|
||||
### [Contributing](https://controlpanel.gg/docs/Contributing/contributing "Contributing")
|
||||
### [Contributing](https://ctrlpanel.gg/docs/Contributing/contributing "Contributing")
|
||||
|
||||
### [Donating](https://controlpanel.gg/docs/Contributing/donating "Donating")
|
||||
### [Donating](https://ctrlpanel.gg/docs/Contributing/donating "Donating")
|
||||
|
||||
|
||||
|
||||
# Preview
|
||||
|
||||
### Server Creation
|
||||

|
||||

|
||||
|
||||
### Overview
|
||||

|
||||

|
||||
|
||||
### Example server products
|
||||

|
||||

|
||||
|
||||
### Ticket System
|
||||

|
||||

|
||||
|
||||
### Voucher System
|
||||

|
||||
|
||||
### Partner System
|
||||

|
||||
|
||||
|
||||
|
||||
|
|
|
@ -5,8 +5,9 @@ namespace App\Classes;
|
|||
use App\Models\Egg;
|
||||
use App\Models\Nest;
|
||||
use App\Models\Node;
|
||||
use App\Models\Server;
|
||||
use App\Models\Product;
|
||||
use App\Models\Server;
|
||||
use App\Models\User;
|
||||
use Exception;
|
||||
use Illuminate\Http\Client\PendingRequest;
|
||||
use Illuminate\Http\Client\Response;
|
||||
|
@ -22,136 +23,160 @@ class Pterodactyl
|
|||
public static function client()
|
||||
{
|
||||
return Http::withHeaders([
|
||||
'Authorization' => 'Bearer ' . config("SETTINGS::SYSTEM:PTERODACTYL:TOKEN"),
|
||||
'Content-type' => 'application/json',
|
||||
'Accept' => 'Application/vnd.pterodactyl.v1+json',
|
||||
])->baseUrl(config("SETTINGS::SYSTEM:PTERODACTYL:URL") . '/api');
|
||||
'Authorization' => 'Bearer ' . config('SETTINGS::SYSTEM:PTERODACTYL:TOKEN'),
|
||||
'Content-type' => 'application/json',
|
||||
'Accept' => 'Application/vnd.pterodactyl.v1+json',
|
||||
])->baseUrl(config('SETTINGS::SYSTEM:PTERODACTYL:URL') . '/api');
|
||||
}
|
||||
|
||||
public static function clientAdmin()
|
||||
{
|
||||
return Http::withHeaders([
|
||||
'Authorization' => 'Bearer ' . config("SETTINGS::SYSTEM:PTERODACTYL:ADMIN_USER_TOKEN"),
|
||||
'Content-type' => 'application/json',
|
||||
'Accept' => 'Application/vnd.pterodactyl.v1+json',
|
||||
])->baseUrl(config("SETTINGS::SYSTEM:PTERODACTYL:URL") . '/api');
|
||||
'Authorization' => 'Bearer ' . config('SETTINGS::SYSTEM:PTERODACTYL:ADMIN_USER_TOKEN'),
|
||||
'Content-type' => 'application/json',
|
||||
'Accept' => 'Application/vnd.pterodactyl.v1+json',
|
||||
])->baseUrl(config('SETTINGS::SYSTEM:PTERODACTYL:URL') . '/api');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Exception
|
||||
*/
|
||||
private static function getException(string $message = "", int $status = 0): Exception
|
||||
private static function getException(string $message = '', int $status = 0): Exception
|
||||
{
|
||||
if ($status == 404) {
|
||||
return new Exception("Ressource does not exist on pterodactyl - " . $message, 404);
|
||||
return new Exception('Ressource does not exist on pterodactyl - ' . $message, 404);
|
||||
}
|
||||
|
||||
if ($status == 403) {
|
||||
return new Exception("No permission on pterodactyl, check pterodactyl token and permissions - " . $message, 403);
|
||||
return new Exception('No permission on pterodactyl, check pterodactyl token and permissions - ' . $message, 403);
|
||||
}
|
||||
|
||||
if ($status == 401) {
|
||||
return new Exception("No pterodactyl token set - " . $message, 401);
|
||||
return new Exception('No pterodactyl token set - ' . $message, 401);
|
||||
}
|
||||
|
||||
if ($status == 500) {
|
||||
return new Exception("Pterodactyl server error - " . $message, 500);
|
||||
return new Exception('Pterodactyl server error - ' . $message, 500);
|
||||
}
|
||||
|
||||
return new Exception('Request Failed, is pterodactyl set-up correctly? - ' . $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Nest $nest
|
||||
* @param Nest $nest
|
||||
* @return mixed
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function getEggs(Nest $nest)
|
||||
{
|
||||
try {
|
||||
$response = self::client()->get("/application/nests/{$nest->id}/eggs?include=nest,variables&per_page=" . config("SETTINGS::SYSTEM:PTERODACTYL:PER_PAGE_LIMIT"));
|
||||
$response = self::client()->get("/application/nests/{$nest->id}/eggs?include=nest,variables&per_page=" . config('SETTINGS::SYSTEM:PTERODACTYL:PER_PAGE_LIMIT'));
|
||||
} catch (Exception $e) {
|
||||
throw self::getException($e->getMessage());
|
||||
}
|
||||
if ($response->failed()) throw self::getException("Failed to get eggs from pterodactyl - ", $response->status());
|
||||
if ($response->failed()) {
|
||||
throw self::getException('Failed to get eggs from pterodactyl - ', $response->status());
|
||||
}
|
||||
|
||||
return $response->json()['data'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function getNodes()
|
||||
{
|
||||
try {
|
||||
$response = self::client()->get('/application/nodes?per_page=' . config("SETTINGS::SYSTEM:PTERODACTYL:PER_PAGE_LIMIT"));
|
||||
$response = self::client()->get('/application/nodes?per_page=' . config('SETTINGS::SYSTEM:PTERODACTYL:PER_PAGE_LIMIT'));
|
||||
} catch (Exception $e) {
|
||||
throw self::getException($e->getMessage());
|
||||
}
|
||||
if ($response->failed()) throw self::getException("Failed to get nodes from pterodactyl - ", $response->status());
|
||||
if ($response->failed()) {
|
||||
throw self::getException('Failed to get nodes from pterodactyl - ', $response->status());
|
||||
}
|
||||
|
||||
return $response->json()['data'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*
|
||||
* @throws Exception
|
||||
* @description Returns the infos of a single node
|
||||
*/
|
||||
public static function getNode($id) {
|
||||
public static function getNode($id)
|
||||
{
|
||||
try {
|
||||
$response = self::client()->get('/application/nodes/' . $id);
|
||||
} catch(Exception $e) {
|
||||
throw self::getException($e->getMessage());
|
||||
}
|
||||
if($response->failed()) throw self::getException("Failed to get node id " . $id . " - " . $response->status());
|
||||
return $response->json()['attributes'];
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static function getServers() {
|
||||
try {
|
||||
$response = self::client()->get('/application/servers?per_page=' . config("SETTINGS::SYSTEM:PTERODACTYL:PER_PAGE_LIMIT"));
|
||||
} catch (Exception $e) {
|
||||
throw self::getException($e->getMessage());
|
||||
}
|
||||
if($response->failed()) throw self::getException("Failed to get list of servers - ", $response->status());
|
||||
if ($response->failed()) {
|
||||
throw self::getException('Failed to get node id ' . $id . ' - ' . $response->status());
|
||||
}
|
||||
|
||||
return $response->json()['attributes'];
|
||||
}
|
||||
|
||||
public static function getServers()
|
||||
{
|
||||
try {
|
||||
$response = self::client()->get('/application/servers?per_page=' . config('SETTINGS::SYSTEM:PTERODACTYL:PER_PAGE_LIMIT'));
|
||||
} catch (Exception $e) {
|
||||
throw self::getException($e->getMessage());
|
||||
}
|
||||
if ($response->failed()) {
|
||||
throw self::getException('Failed to get list of servers - ', $response->status());
|
||||
}
|
||||
|
||||
return $response->json()['data'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function getNests()
|
||||
{
|
||||
try {
|
||||
$response = self::client()->get('/application/nests?per_page=' . config("SETTINGS::SYSTEM:PTERODACTYL:PER_PAGE_LIMIT"));
|
||||
$response = self::client()->get('/application/nests?per_page=' . config('SETTINGS::SYSTEM:PTERODACTYL:PER_PAGE_LIMIT'));
|
||||
} catch (Exception $e) {
|
||||
throw self::getException($e->getMessage());
|
||||
}
|
||||
if ($response->failed()) throw self::getException("Failed to get nests from pterodactyl", $response->status());
|
||||
if ($response->failed()) {
|
||||
throw self::getException('Failed to get nests from pterodactyl', $response->status());
|
||||
}
|
||||
|
||||
return $response->json()['data'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function getLocations()
|
||||
{
|
||||
try {
|
||||
$response = self::client()->get('/application/locations?per_page=' . config("SETTINGS::SYSTEM:PTERODACTYL:PER_PAGE_LIMIT"));
|
||||
$response = self::client()->get('/application/locations?per_page=' . config('SETTINGS::SYSTEM:PTERODACTYL:PER_PAGE_LIMIT'));
|
||||
} catch (Exception $e) {
|
||||
throw self::getException($e->getMessage());
|
||||
}
|
||||
if ($response->failed()) throw self::getException("Failed to get locations from pterodactyl - ", $response->status());
|
||||
if ($response->failed()) {
|
||||
throw self::getException('Failed to get locations from pterodactyl - ', $response->status());
|
||||
}
|
||||
|
||||
return $response->json()['data'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Node $node
|
||||
* @param Node $node
|
||||
* @return mixed
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function getFreeAllocationId(Node $node)
|
||||
|
@ -160,8 +185,9 @@ class Pterodactyl
|
|||
}
|
||||
|
||||
/**
|
||||
* @param Node $node
|
||||
* @param Node $node
|
||||
* @return array|mixed|null
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function getFreeAllocations(Node $node)
|
||||
|
@ -172,7 +198,9 @@ class Pterodactyl
|
|||
if (isset($response['data'])) {
|
||||
if (!empty($response['data'])) {
|
||||
foreach ($response['data'] as $allocation) {
|
||||
if (!$allocation['attributes']['assigned']) array_push($freeAllocations, $allocation);
|
||||
if (!$allocation['attributes']['assigned']) {
|
||||
array_push($freeAllocations, $allocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -181,8 +209,9 @@ class Pterodactyl
|
|||
}
|
||||
|
||||
/**
|
||||
* @param Node $node
|
||||
* @param Node $node
|
||||
* @return array|mixed
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function getAllocations(Node $node)
|
||||
|
@ -193,51 +222,53 @@ class Pterodactyl
|
|||
} catch (Exception $e) {
|
||||
throw self::getException($e->getMessage());
|
||||
}
|
||||
if ($response->failed()) throw self::getException("Failed to get allocations from pterodactyl - ", $response->status());
|
||||
if ($response->failed()) {
|
||||
throw self::getException('Failed to get allocations from pterodactyl - ', $response->status());
|
||||
}
|
||||
|
||||
return $response->json();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param String $route
|
||||
* @param string $route
|
||||
* @return string
|
||||
*/
|
||||
public static function url(string $route): string
|
||||
{
|
||||
return config("SETTINGS::SYSTEM:PTERODACTYL:URL") . $route;
|
||||
return config('SETTINGS::SYSTEM:PTERODACTYL:URL') . $route;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
* @param Egg $egg
|
||||
* @param int $allocationId
|
||||
* @param Server $server
|
||||
* @param Egg $egg
|
||||
* @param int $allocationId
|
||||
* @return Response
|
||||
*/
|
||||
public static function createServer(Server $server, Egg $egg, int $allocationId)
|
||||
{
|
||||
return self::client()->post("/application/servers", [
|
||||
"name" => $server->name,
|
||||
"external_id" => $server->id,
|
||||
"user" => $server->user->pterodactyl_id,
|
||||
"egg" => $egg->id,
|
||||
"docker_image" => $egg->docker_image,
|
||||
"startup" => $egg->startup,
|
||||
"environment" => $egg->getEnvironmentVariables(),
|
||||
"limits" => [
|
||||
"memory" => $server->product->memory,
|
||||
"swap" => $server->product->swap,
|
||||
"disk" => $server->product->disk,
|
||||
"io" => $server->product->io,
|
||||
"cpu" => $server->product->cpu
|
||||
return self::client()->post('/application/servers', [
|
||||
'name' => $server->name,
|
||||
'external_id' => $server->id,
|
||||
'user' => $server->user->pterodactyl_id,
|
||||
'egg' => $egg->id,
|
||||
'docker_image' => $egg->docker_image,
|
||||
'startup' => $egg->startup,
|
||||
'environment' => $egg->getEnvironmentVariables(),
|
||||
'limits' => [
|
||||
'memory' => $server->product->memory,
|
||||
'swap' => $server->product->swap,
|
||||
'disk' => $server->product->disk,
|
||||
'io' => $server->product->io,
|
||||
'cpu' => $server->product->cpu,
|
||||
],
|
||||
"feature_limits" => [
|
||||
"databases" => $server->product->databases,
|
||||
"backups" => $server->product->backups,
|
||||
"allocations" => $server->product->allocations,
|
||||
'feature_limits' => [
|
||||
'databases' => $server->product->databases,
|
||||
'backups' => $server->product->backups,
|
||||
'allocations' => $server->product->allocations,
|
||||
],
|
||||
'allocation' => [
|
||||
'default' => $allocationId,
|
||||
],
|
||||
"allocation" => [
|
||||
"default" => $allocationId
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -248,7 +279,9 @@ class Pterodactyl
|
|||
} catch (Exception $e) {
|
||||
throw self::getException($e->getMessage());
|
||||
}
|
||||
if ($response->failed()) throw self::getException("Failed to suspend server from pterodactyl - ", $response->status());
|
||||
if ($response->failed()) {
|
||||
throw self::getException('Failed to suspend server from pterodactyl - ', $response->status());
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
@ -260,14 +293,17 @@ class Pterodactyl
|
|||
} catch (Exception $e) {
|
||||
throw self::getException($e->getMessage());
|
||||
}
|
||||
if ($response->failed()) throw self::getException("Failed to unsuspend server from pterodactyl - ", $response->status());
|
||||
if ($response->failed()) {
|
||||
throw self::getException('Failed to unsuspend server from pterodactyl - ', $response->status());
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user by pterodactyl id
|
||||
* @param int $pterodactylId
|
||||
*
|
||||
* @param int $pterodactylId
|
||||
* @return mixed
|
||||
*/
|
||||
public function getUser(int $pterodactylId)
|
||||
|
@ -277,14 +313,17 @@ class Pterodactyl
|
|||
} catch (Exception $e) {
|
||||
throw self::getException($e->getMessage());
|
||||
}
|
||||
if ($response->failed()) throw self::getException("Failed to get user from pterodactyl - ", $response->status());
|
||||
if ($response->failed()) {
|
||||
throw self::getException('Failed to get user from pterodactyl - ', $response->status());
|
||||
}
|
||||
|
||||
return $response->json()['attributes'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get serverAttributes by pterodactyl id
|
||||
* @param int $pterodactylId
|
||||
*
|
||||
* @param int $pterodactylId
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getServerAttributes(int $pterodactylId, bool $deleteOn404 = false)
|
||||
|
@ -297,51 +336,70 @@ class Pterodactyl
|
|||
|
||||
//print response body
|
||||
|
||||
|
||||
|
||||
if ($response->failed()){
|
||||
if($deleteOn404){ //Delete the server if it does not exist (server deleted on pterodactyl)
|
||||
if ($response->failed()) {
|
||||
if ($deleteOn404) { //Delete the server if it does not exist (server deleted on pterodactyl)
|
||||
Server::where('pterodactyl_id', $pterodactylId)->first()->delete();
|
||||
|
||||
return;
|
||||
} else {
|
||||
throw self::getException('Failed to get server attributes from pterodactyl - ', $response->status());
|
||||
}
|
||||
else throw self::getException("Failed to get server attributes from pterodactyl - ", $response->status());
|
||||
}
|
||||
|
||||
return $response->json()['attributes'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Server Resources
|
||||
* @param Server $server
|
||||
* @param Product $product
|
||||
*
|
||||
* @param Server $server
|
||||
* @param Product $product
|
||||
* @return Response
|
||||
*/
|
||||
public static function updateServer(Server $server, Product $product)
|
||||
{
|
||||
return self::client()->patch("/application/servers/{$server->pterodactyl_id}/build", [
|
||||
"allocation" => $server->allocation,
|
||||
"memory" => $product->memory,
|
||||
"swap" => $product->swap,
|
||||
"disk" => $product->disk,
|
||||
"io" => $product->io,
|
||||
"cpu" => $product->cpu,
|
||||
"threads" => null,
|
||||
"feature_limits" => [
|
||||
"databases" => $product->databases,
|
||||
"backups" => $product->backups,
|
||||
"allocations" => $product->allocations,
|
||||
]
|
||||
'allocation' => $server->allocation,
|
||||
'memory' => $product->memory,
|
||||
'swap' => $product->swap,
|
||||
'disk' => $product->disk,
|
||||
'io' => $product->io,
|
||||
'cpu' => $product->cpu,
|
||||
'threads' => null,
|
||||
'feature_limits' => [
|
||||
'databases' => $product->databases,
|
||||
'backups' => $product->backups,
|
||||
'allocations' => $product->allocations,
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the owner of a server
|
||||
*
|
||||
* @param int $userId
|
||||
* @param Server $server
|
||||
* @return mixed
|
||||
*/
|
||||
public static function updateServerOwner(Server $server, int $userId)
|
||||
{
|
||||
return self::client()->patch("/application/servers/{$server->pterodactyl_id}/details", [
|
||||
'name' => $server->name,
|
||||
'user' => $userId,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Power Action Specific Server
|
||||
* @param Server $server
|
||||
* @param string $action
|
||||
*
|
||||
* @param Server $server
|
||||
* @param string $action
|
||||
* @return Response
|
||||
*/
|
||||
public static function powerAction(Server $server, $action)
|
||||
{
|
||||
return self::clientAdmin()->post("/client/servers/{$server->identifier}/power", [
|
||||
"signal" => $action
|
||||
'signal' => $action,
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -350,16 +408,16 @@ class Pterodactyl
|
|||
*/
|
||||
public static function getClientUser()
|
||||
{
|
||||
return self::clientAdmin()->get("/client/account");
|
||||
return self::clientAdmin()->get('/client/account');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if node has enough free resources to allocate the given resources
|
||||
* @param Node $node
|
||||
* @param int $requireMemory
|
||||
* @param int $requireDisk
|
||||
* @return boolean
|
||||
*
|
||||
* @param Node $node
|
||||
* @param int $requireMemory
|
||||
* @param int $requireDisk
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkNodeResources(Node $node, int $requireMemory, int $requireDisk)
|
||||
{
|
||||
|
@ -369,14 +427,15 @@ class Pterodactyl
|
|||
throw self::getException($e->getMessage());
|
||||
}
|
||||
$node = $response['attributes'];
|
||||
$freeMemory = ($node['memory']*($node['memory_overallocate']+100)/100) - $node['allocated_resources']['memory'];
|
||||
$freeDisk = ($node['disk']*($node['disk_overallocate']+100)/100) - $node['allocated_resources']['disk'];
|
||||
$freeMemory = ($node['memory'] * ($node['memory_overallocate'] + 100) / 100) - $node['allocated_resources']['memory'];
|
||||
$freeDisk = ($node['disk'] * ($node['disk_overallocate'] + 100) / 100) - $node['allocated_resources']['disk'];
|
||||
if ($freeMemory < $requireMemory) {
|
||||
return false;
|
||||
}
|
||||
if ($freeDisk < $requireDisk) {
|
||||
}
|
||||
if ($freeDisk < $requireDisk) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,9 +10,8 @@ class Invoices
|
|||
{
|
||||
public function __construct()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function updateSettings(Request $request)
|
||||
{
|
||||
|
@ -22,29 +21,27 @@ class Invoices
|
|||
|
||||
$values = [
|
||||
//SETTINGS::VALUE => REQUEST-VALUE (coming from the html-form)
|
||||
"SETTINGS::INVOICE:COMPANY_NAME" => "company-name",
|
||||
"SETTINGS::INVOICE:COMPANY_ADDRESS" => "company-address",
|
||||
"SETTINGS::INVOICE:COMPANY_PHONE" => "company-phone",
|
||||
"SETTINGS::INVOICE:COMPANY_MAIL" => "company-mail",
|
||||
"SETTINGS::INVOICE:COMPANY_VAT" => "company-vat",
|
||||
"SETTINGS::INVOICE:COMPANY_WEBSITE" => "company-web",
|
||||
"SETTINGS::INVOICE:PREFIX" => "invoice-prefix",
|
||||
"SETTINGS::INVOICE:ENABLED" => "enable-invoices",
|
||||
'SETTINGS::INVOICE:COMPANY_NAME' => 'company-name',
|
||||
'SETTINGS::INVOICE:COMPANY_ADDRESS' => 'company-address',
|
||||
'SETTINGS::INVOICE:COMPANY_PHONE' => 'company-phone',
|
||||
'SETTINGS::INVOICE:COMPANY_MAIL' => 'company-mail',
|
||||
'SETTINGS::INVOICE:COMPANY_VAT' => 'company-vat',
|
||||
'SETTINGS::INVOICE:COMPANY_WEBSITE' => 'company-web',
|
||||
'SETTINGS::INVOICE:PREFIX' => 'invoice-prefix',
|
||||
'SETTINGS::INVOICE:ENABLED' => 'enable-invoices',
|
||||
];
|
||||
|
||||
foreach ($values as $key => $value) {
|
||||
$param = $request->get($value);
|
||||
|
||||
Settings::where('key', $key)->updateOrCreate(['key' => $key], ['value' => $param]);
|
||||
Cache::forget("setting" . ':' . $key);
|
||||
Cache::forget('setting'.':'.$key);
|
||||
}
|
||||
|
||||
|
||||
if ($request->hasFile('logo')) {
|
||||
$request->file('logo')->storeAs('public', 'logo.png');
|
||||
}
|
||||
|
||||
|
||||
return redirect(route('admin.settings.index') . '#invoices')->with('success', __('Invoice settings updated!'));
|
||||
return redirect(route('admin.settings.index').'#invoices')->with('success', __('Invoice settings updated!'));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,14 +8,12 @@ use Illuminate\Support\Facades\Cache;
|
|||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
|
||||
class Language
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function updateSettings(Request $request)
|
||||
{
|
||||
|
@ -28,34 +26,31 @@ class Language
|
|||
'datatable-language' => 'required|string',
|
||||
]);
|
||||
|
||||
|
||||
if ($validator->fails()) {
|
||||
return redirect(route('admin.settings.index') . '#language')->with('error', __('Language settings have not been updated!'))->withErrors($validator);
|
||||
return redirect(route('admin.settings.index').'#language')->with('error', __('Language settings have not been updated!'))->withErrors($validator);
|
||||
}
|
||||
|
||||
$values = [
|
||||
//SETTINGS::VALUE => REQUEST-VALUE (coming from the html-form)
|
||||
"SETTINGS::LOCALE:DEFAULT" => "defaultLanguage",
|
||||
"SETTINGS::LOCALE:DYNAMIC" => "autotranslate",
|
||||
"SETTINGS::LOCALE:CLIENTS_CAN_CHANGE" => "canClientChangeLanguage",
|
||||
"SETTINGS::LOCALE:AVAILABLE" => "languages",
|
||||
"SETTINGS::LOCALE:DATATABLES" => "datatable-language"
|
||||
'SETTINGS::LOCALE:DEFAULT' => 'defaultLanguage',
|
||||
'SETTINGS::LOCALE:DYNAMIC' => 'autotranslate',
|
||||
'SETTINGS::LOCALE:CLIENTS_CAN_CHANGE' => 'canClientChangeLanguage',
|
||||
'SETTINGS::LOCALE:AVAILABLE' => 'languages',
|
||||
'SETTINGS::LOCALE:DATATABLES' => 'datatable-language',
|
||||
];
|
||||
|
||||
|
||||
foreach ($values as $key => $value) {
|
||||
$param = $request->get($value);
|
||||
|
||||
if (is_array($param)) {
|
||||
$param = implode(",", $param);
|
||||
$param = implode(',', $param);
|
||||
}
|
||||
|
||||
Settings::where('key', $key)->updateOrCreate(['key' => $key], ['value' => $param]);
|
||||
Cache::forget("setting" . ':' . $key);
|
||||
Session::remove("locale");
|
||||
Cache::forget('setting'.':'.$key);
|
||||
Session::remove('locale');
|
||||
}
|
||||
|
||||
|
||||
return redirect(route('admin.settings.index') . '#language')->with('success', __('Language settings updated!'));
|
||||
return redirect(route('admin.settings.index').'#language')->with('success', __('Language settings updated!'));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,12 +7,11 @@ use Illuminate\Http\Request;
|
|||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
|
||||
class Misc
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
public function updateSettings(Request $request)
|
||||
|
@ -40,21 +39,23 @@ class Misc
|
|||
'enable_referral' => 'nullable|string',
|
||||
'referral_reward' => 'nullable|numeric',
|
||||
'referral_allowed' => 'nullable|string',
|
||||
'always_give_commission' => 'nullable|string',
|
||||
'referral_percentage' => 'nullable|numeric',
|
||||
'referral_mode' => 'nullable|string',
|
||||
'ticket_enabled' => 'nullable|string',
|
||||
'ticket_notify' => 'string',
|
||||
]);
|
||||
|
||||
$validator->after(function ($validator) use ($request) {
|
||||
// if enable-recaptcha is true then recaptcha-site-key and recaptcha-secret-key must be set
|
||||
if ($request->get('enable-recaptcha') == 'true' && (!$request->get('recaptcha-site-key') || !$request->get('recaptcha-secret-key'))) {
|
||||
if ($request->get('enable-recaptcha') == 'true' && (! $request->get('recaptcha-site-key') || ! $request->get('recaptcha-secret-key'))) {
|
||||
$validator->errors()->add('recaptcha-site-key', 'The site key is required if recaptcha is enabled.');
|
||||
$validator->errors()->add('recaptcha-secret-key', 'The secret key is required if recaptcha is enabled.');
|
||||
}
|
||||
});
|
||||
|
||||
if ($validator->fails()) {
|
||||
return redirect(route('admin.settings.index') . '#misc')->with('error', __('Misc settings have not been updated!'))->withErrors($validator)
|
||||
return redirect(route('admin.settings.index').'#misc')->with('error', __('Misc settings have not been updated!'))->withErrors($validator)
|
||||
->withInput();
|
||||
}
|
||||
|
||||
|
@ -66,30 +67,31 @@ class Misc
|
|||
}
|
||||
|
||||
$values = [
|
||||
"SETTINGS::DISCORD:BOT_TOKEN" => "discord-bot-token",
|
||||
"SETTINGS::DISCORD:CLIENT_ID" => "discord-client-id",
|
||||
"SETTINGS::DISCORD:CLIENT_SECRET" => "discord-client-secret",
|
||||
"SETTINGS::DISCORD:GUILD_ID" => "discord-guild-id",
|
||||
"SETTINGS::DISCORD:INVITE_URL" => "discord-invite-url",
|
||||
"SETTINGS::DISCORD:ROLE_ID" => "discord-role-id",
|
||||
"SETTINGS::RECAPTCHA:SITE_KEY" => "recaptcha-site-key",
|
||||
"SETTINGS::RECAPTCHA:SECRET_KEY" => "recaptcha-secret-key",
|
||||
"SETTINGS::RECAPTCHA:ENABLED" => "enable-recaptcha",
|
||||
"SETTINGS::MAIL:MAILER" => "mailservice",
|
||||
"SETTINGS::MAIL:HOST" => "mailhost",
|
||||
"SETTINGS::MAIL:PORT" => "mailport",
|
||||
"SETTINGS::MAIL:USERNAME" => "mailusername",
|
||||
"SETTINGS::MAIL:PASSWORD" => "mailpassword",
|
||||
"SETTINGS::MAIL:ENCRYPTION" => "mailencryption",
|
||||
"SETTINGS::MAIL:FROM_ADDRESS" => "mailfromadress",
|
||||
"SETTINGS::MAIL:FROM_NAME" => "mailfromname",
|
||||
"SETTINGS::REFERRAL::ENABLED" => "enable_referral",
|
||||
"SETTINGS::REFERRAL::REWARD" => "referral_reward",
|
||||
"SETTINGS::REFERRAL::ALLOWED" => "referral_allowed",
|
||||
"SETTINGS::REFERRAL:MODE" => "referral_mode",
|
||||
"SETTINGS::REFERRAL:PERCENTAGE" => "referral_percentage",
|
||||
"SETTINGS::TICKET:ENABLED" => "ticket_enabled"
|
||||
|
||||
'SETTINGS::DISCORD:BOT_TOKEN' => 'discord-bot-token',
|
||||
'SETTINGS::DISCORD:CLIENT_ID' => 'discord-client-id',
|
||||
'SETTINGS::DISCORD:CLIENT_SECRET' => 'discord-client-secret',
|
||||
'SETTINGS::DISCORD:GUILD_ID' => 'discord-guild-id',
|
||||
'SETTINGS::DISCORD:INVITE_URL' => 'discord-invite-url',
|
||||
'SETTINGS::DISCORD:ROLE_ID' => 'discord-role-id',
|
||||
'SETTINGS::RECAPTCHA:SITE_KEY' => 'recaptcha-site-key',
|
||||
'SETTINGS::RECAPTCHA:SECRET_KEY' => 'recaptcha-secret-key',
|
||||
'SETTINGS::RECAPTCHA:ENABLED' => 'enable-recaptcha',
|
||||
'SETTINGS::MAIL:MAILER' => 'mailservice',
|
||||
'SETTINGS::MAIL:HOST' => 'mailhost',
|
||||
'SETTINGS::MAIL:PORT' => 'mailport',
|
||||
'SETTINGS::MAIL:USERNAME' => 'mailusername',
|
||||
'SETTINGS::MAIL:PASSWORD' => 'mailpassword',
|
||||
'SETTINGS::MAIL:ENCRYPTION' => 'mailencryption',
|
||||
'SETTINGS::MAIL:FROM_ADDRESS' => 'mailfromadress',
|
||||
'SETTINGS::MAIL:FROM_NAME' => 'mailfromname',
|
||||
'SETTINGS::REFERRAL::ENABLED' => 'enable_referral',
|
||||
'SETTINGS::REFERRAL::REWARD' => 'referral_reward',
|
||||
'SETTINGS::REFERRAL::ALLOWED' => 'referral_allowed',
|
||||
'SETTINGS::REFERRAL:MODE' => 'referral_mode',
|
||||
'SETTINGS::REFERRAL::ALWAYS_GIVE_COMMISSION' => 'always_give_commission',
|
||||
'SETTINGS::REFERRAL:PERCENTAGE' => 'referral_percentage',
|
||||
'SETTINGS::TICKET:ENABLED' => 'ticket_enabled',
|
||||
'SETTINGS::TICKET:NOTIFY' => 'ticket_notify',
|
||||
|
||||
];
|
||||
|
||||
|
@ -97,10 +99,9 @@ class Misc
|
|||
$param = $request->get($value);
|
||||
|
||||
Settings::where('key', $key)->updateOrCreate(['key' => $key], ['value' => $param]);
|
||||
Cache::forget("setting" . ':' . $key);
|
||||
Cache::forget('setting'.':'.$key);
|
||||
}
|
||||
|
||||
|
||||
return redirect(route('admin.settings.index') . '#misc')->with('success', __('Misc settings updated!'));
|
||||
return redirect(route('admin.settings.index').'#misc')->with('success', __('Misc settings updated!'));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,55 +7,52 @@ use Illuminate\Http\Request;
|
|||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
|
||||
class Payments
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function updateSettings(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
"paypal-client_id" => "nullable|string",
|
||||
"paypal-client-secret" => "nullable|string",
|
||||
"paypal-sandbox-secret" => "nullable|string",
|
||||
"stripe-secret-key" => "nullable|string",
|
||||
"stripe-endpoint-secret" => "nullable|string",
|
||||
"stripe-test-secret-key" => "nullable|string",
|
||||
"stripe-test-endpoint-secret" => "nullable|string",
|
||||
"stripe-methods" => "nullable|string",
|
||||
"sales-tax" => "nullable|numeric",
|
||||
'paypal-client_id' => 'nullable|string',
|
||||
'paypal-client-secret' => 'nullable|string',
|
||||
'paypal-sandbox-secret' => 'nullable|string',
|
||||
'stripe-secret-key' => 'nullable|string',
|
||||
'stripe-endpoint-secret' => 'nullable|string',
|
||||
'stripe-test-secret-key' => 'nullable|string',
|
||||
'stripe-test-endpoint-secret' => 'nullable|string',
|
||||
'stripe-methods' => 'nullable|string',
|
||||
'sales-tax' => 'nullable|numeric',
|
||||
]);
|
||||
if ($validator->fails()) {
|
||||
return redirect(route('admin.settings.index') . '#payment')->with('error', __('Payment settings have not been updated!'))->withErrors($validator)
|
||||
return redirect(route('admin.settings.index').'#payment')->with('error', __('Payment settings have not been updated!'))->withErrors($validator)
|
||||
->withInput();
|
||||
}
|
||||
|
||||
$values = [
|
||||
//SETTINGS::VALUE => REQUEST-VALUE (coming from the html-form)
|
||||
"SETTINGS::PAYMENTS:PAYPAL:SECRET" => "paypal-client-secret",
|
||||
"SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID" => "paypal-client-id",
|
||||
"SETTINGS::PAYMENTS:PAYPAL:SANDBOX_SECRET" => "paypal-sandbox-secret",
|
||||
"SETTINGS::PAYMENTS:PAYPAL:SANDBOX_CLIENT_ID" => "paypal-sandbox-id",
|
||||
"SETTINGS::PAYMENTS:STRIPE:SECRET" => "stripe-secret",
|
||||
"SETTINGS::PAYMENTS:STRIPE:ENDPOINT_SECRET" => "stripe-endpoint-secret",
|
||||
"SETTINGS::PAYMENTS:STRIPE:TEST_SECRET" => "stripe-test-secret",
|
||||
"SETTINGS::PAYMENTS:STRIPE:ENDPOINT_TEST_SECRET" => "stripe-endpoint-test-secret",
|
||||
"SETTINGS::PAYMENTS:STRIPE:METHODS" => "stripe-methods",
|
||||
"SETTINGS::PAYMENTS:SALES_TAX" => "sales-tax"
|
||||
'SETTINGS::PAYMENTS:PAYPAL:SECRET' => 'paypal-client-secret',
|
||||
'SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID' => 'paypal-client-id',
|
||||
'SETTINGS::PAYMENTS:PAYPAL:SANDBOX_SECRET' => 'paypal-sandbox-secret',
|
||||
'SETTINGS::PAYMENTS:PAYPAL:SANDBOX_CLIENT_ID' => 'paypal-sandbox-id',
|
||||
'SETTINGS::PAYMENTS:STRIPE:SECRET' => 'stripe-secret',
|
||||
'SETTINGS::PAYMENTS:STRIPE:ENDPOINT_SECRET' => 'stripe-endpoint-secret',
|
||||
'SETTINGS::PAYMENTS:STRIPE:TEST_SECRET' => 'stripe-test-secret',
|
||||
'SETTINGS::PAYMENTS:STRIPE:ENDPOINT_TEST_SECRET' => 'stripe-endpoint-test-secret',
|
||||
'SETTINGS::PAYMENTS:STRIPE:METHODS' => 'stripe-methods',
|
||||
'SETTINGS::PAYMENTS:SALES_TAX' => 'sales-tax',
|
||||
];
|
||||
|
||||
|
||||
foreach ($values as $key => $value) {
|
||||
$param = $request->get($value);
|
||||
|
||||
Settings::where('key', $key)->updateOrCreate(['key' => $key], ['value' => $param]);
|
||||
Cache::forget("setting" . ':' . $key);
|
||||
Cache::forget('setting'.':'.$key);
|
||||
}
|
||||
|
||||
return redirect(route('admin.settings.index') . '#payment')->with('success', __('Payment settings updated!'));
|
||||
return redirect(route('admin.settings.index').'#payment')->with('success', __('Payment settings updated!'));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,68 +7,85 @@ use App\Models\Settings;
|
|||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Qirolab\Theme\Theme;
|
||||
|
||||
|
||||
class System
|
||||
{
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
public function checkPteroClientkey(){
|
||||
$response = Pterodactyl::getClientUser();
|
||||
public function checkPteroClientkey()
|
||||
{
|
||||
$response = Pterodactyl::getClientUser();
|
||||
|
||||
if ($response->failed()){ return redirect()->back()->with('error', __('Your Key or URL is not correct')); }
|
||||
return redirect()->back()->with('success', __('Everything is good!'));
|
||||
}
|
||||
if ($response->failed()) {
|
||||
return redirect()->back()->with('error', __('Your Key or URL is not correct'));
|
||||
}
|
||||
|
||||
return redirect()->back()->with('success', __('Everything is good!'));
|
||||
}
|
||||
|
||||
public function updateSettings(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
"register-ip-check" => "string",
|
||||
"server-create-charge-first-hour" => "string",
|
||||
"credits-display-name" => "required|string",
|
||||
"allocation-limit" => "required|min:0|integer",
|
||||
"force-email-verification" => "string",
|
||||
"force-discord-verification" => "string",
|
||||
"initial-credits" => "required|min:0|integer",
|
||||
"initial-server-limit" => "required|min:0|integer",
|
||||
"credits-reward-amount-discord" => "required|min:0|integer",
|
||||
"credits-reward-amount-email" => "required|min:0|integer",
|
||||
"server-limit-discord" => "required|min:0|integer",
|
||||
"server-limit-email" => "required|min:0|integer",
|
||||
"server-limit-purchase" => "required|min:0|integer",
|
||||
"pterodactyl-api-key" => "required|string",
|
||||
"pterodactyl-url" => "required|string",
|
||||
"per-page-limit" => "required|min:0|integer",
|
||||
"pterodactyl-admin-api-key" => "required|string",
|
||||
"enable-upgrades" => "string",
|
||||
"enable-disable-servers" => "string",
|
||||
'register-ip-check' => 'string',
|
||||
'server-create-charge-first-hour' => 'string',
|
||||
'credits-display-name' => 'required|string',
|
||||
'allocation-limit' => 'required|min:0|integer',
|
||||
'force-email-verification' => 'string',
|
||||
'force-discord-verification' => 'string',
|
||||
'initial-credits' => 'required|min:0|integer',
|
||||
'initial-server-limit' => 'required|min:0|integer',
|
||||
'credits-reward-amount-discord' => 'required|min:0|integer',
|
||||
'credits-reward-amount-email' => 'required|min:0|integer',
|
||||
'server-limit-discord' => 'required|min:0|integer',
|
||||
'server-limit-email' => 'required|min:0|integer',
|
||||
'server-limit-purchase' => 'required|min:0|integer',
|
||||
'pterodactyl-api-key' => 'required|string',
|
||||
'pterodactyl-url' => 'required|string',
|
||||
'per-page-limit' => 'required|min:0|integer',
|
||||
'pterodactyl-admin-api-key' => 'required|string',
|
||||
'enable-upgrades' => 'string',
|
||||
'enable-disable-servers' => 'string',
|
||||
'enable-disable-new-users' => 'string',
|
||||
'show-imprint' => 'string',
|
||||
'show-privacy' => 'string',
|
||||
'show-tos' => 'string',
|
||||
'alert-enabled' => 'string',
|
||||
'alter-type' => 'string',
|
||||
'alert-message' => 'string|nullable',
|
||||
'motd-enabled' => 'string',
|
||||
'usefullinks-enabled' => 'string',
|
||||
'motd-message' => 'string|nullable',
|
||||
'seo-title' => 'string|nullable',
|
||||
'seo-description' => 'string|nullable',
|
||||
]);
|
||||
|
||||
$validator->after(function ($validator) use ($request) {
|
||||
// if enable-recaptcha is true then recaptcha-site-key and recaptcha-secret-key must be set
|
||||
if ($request->get('enable-upgrades') == 'true' && (!$request->get('pterodactyl-admin-api-key'))) {
|
||||
if ($request->get('enable-upgrades') == 'true' && (! $request->get('pterodactyl-admin-api-key'))) {
|
||||
$validator->errors()->add('pterodactyl-admin-api-key', 'The admin api key is required when upgrades are enabled.');
|
||||
}
|
||||
});
|
||||
|
||||
if ($validator->fails()) {
|
||||
return redirect(route('admin.settings.index') . '#system')->with('error', __('System settings have not been updated!'))->withErrors($validator)
|
||||
return redirect(route('admin.settings.index').'#system')->with('error', __('System settings have not been updated!'))->withErrors($validator)
|
||||
->withInput();
|
||||
}
|
||||
|
||||
// update Icons from request
|
||||
$this->updateIcons($request);
|
||||
|
||||
|
||||
$values = [
|
||||
|
||||
"SETTINGS::SYSTEM:REGISTER_IP_CHECK" => "register-ip-check",
|
||||
"SETTINGS::SYSTEM:SERVER_CREATE_CHARGE_FIRST_HOUR" => "server-create-charge-first-hour",
|
||||
"SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME" => "credits-display-name",
|
||||
"SETTINGS::SERVER:ALLOCATION_LIMIT" => "allocation-limit",
|
||||
"SETTINGS::USER:MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER" => "minimum-credits",
|
||||
"SETTINGS::USER:FORCE_DISCORD_VERIFICATION" => "force-discord-verification",
|
||||
"SETTINGS::USER:FORCE_EMAIL_VERIFICATION" => "force-email-verification",
|
||||
"SETTINGS::USER:INITIAL_CREDITS" => "initial-credits",
|
||||
|
@ -87,18 +104,34 @@ public function checkPteroClientkey(){
|
|||
"SETTINGS::SYSTEM:ENABLE_UPGRADE" => "enable-upgrade",
|
||||
"SETTINGS::SYSTEM:CREATION_OF_NEW_SERVERS" => "enable-disable-servers",
|
||||
"SETTINGS::SYSTEM:CREATION_OF_NEW_USERS" => "enable-disable-new-users",
|
||||
"SETTINGS::SYSTEM:SHOW_IMPRINT" => "show-imprint",
|
||||
"SETTINGS::SYSTEM:SHOW_PRIVACY" => "show-privacy",
|
||||
"SETTINGS::SYSTEM:SHOW_TOS" => "show-tos",
|
||||
"SETTINGS::SYSTEM:ALERT_ENABLED" => "alert-enabled",
|
||||
"SETTINGS::SYSTEM:ALERT_TYPE" => "alert-type",
|
||||
"SETTINGS::SYSTEM:ALERT_MESSAGE" => "alert-message",
|
||||
"SETTINGS::SYSTEM:THEME" => "theme",
|
||||
"SETTINGS::SYSTEM:MOTD_ENABLED" => "motd-enabled",
|
||||
"SETTINGS::SYSTEM:MOTD_MESSAGE" => "motd-message",
|
||||
"SETTINGS::SYSTEM:USEFULLINKS_ENABLED" => "usefullinks-enabled",
|
||||
"SETTINGS::SYSTEM:SEO_TITLE" => "seo-title",
|
||||
"SETTINGS::SYSTEM:SEO_DESCRIPTION" => "seo-description",
|
||||
];
|
||||
|
||||
|
||||
foreach ($values as $key => $value) {
|
||||
$param = $request->get($value);
|
||||
|
||||
Settings::where('key', $key)->updateOrCreate(['key' => $key], ['value' => $param]);
|
||||
Cache::forget("setting" . ':' . $key);
|
||||
Cache::forget('setting'.':'.$key);
|
||||
}
|
||||
return redirect(route('admin.settings.index') . '#system')->with('success', __('System settings updated!'));
|
||||
}
|
||||
|
||||
//SET THEME
|
||||
$theme = $request->get('theme');
|
||||
Theme::set($theme);
|
||||
|
||||
|
||||
return redirect(route('admin.settings.index').'#system')->with('success', __('System settings updated!'));
|
||||
}
|
||||
|
||||
private function updateIcons(Request $request)
|
||||
{
|
||||
|
|
|
@ -24,9 +24,9 @@ class ChargeCreditsCommand extends Command
|
|||
*/
|
||||
protected $description = 'Charge all users with active servers';
|
||||
|
||||
|
||||
/**
|
||||
* A list of users that have to be notified
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $usersToNotify = [];
|
||||
|
@ -56,24 +56,23 @@ class ChargeCreditsCommand extends Command
|
|||
/** @var User $user */
|
||||
$user = $server->user;
|
||||
|
||||
#charge credits / suspend server
|
||||
//charge credits / suspend server
|
||||
if ($user->credits >= $product->getHourlyPrice()) {
|
||||
$this->line("<fg=blue>{$user->name}</> Current credits: <fg=green>{$user->credits}</> Credits to be removed: <fg=red>{$product->getHourlyPrice()}</>");
|
||||
$user->decrement('credits', $product->getHourlyPrice());
|
||||
} else {
|
||||
try {
|
||||
#suspend server
|
||||
//suspend server
|
||||
$this->line("<fg=yellow>{$server->name}</> from user: <fg=blue>{$user->name}</> has been <fg=red>suspended!</>");
|
||||
$server->suspend();
|
||||
|
||||
#add user to notify list
|
||||
//add user to notify list
|
||||
if (!in_array($user, $this->usersToNotify)) {
|
||||
array_push($this->usersToNotify, $user);
|
||||
}
|
||||
} catch (\Exception $exception) {
|
||||
$this->error($exception->getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -94,8 +93,9 @@ class ChargeCreditsCommand extends Command
|
|||
}
|
||||
}
|
||||
|
||||
#reset array
|
||||
$this->usersToNotify = array();
|
||||
//reset array
|
||||
$this->usersToNotify = [];
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
42
app/Console/Commands/CleanupOpenPayments.php
Normal file
42
app/Console/Commands/CleanupOpenPayments.php
Normal file
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\Payment;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class CleanupOpenPayments extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'payments:open:clear';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Clears all payments from the database that have state "open"';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
// delete all payments that have state "open" and are older than 1 hour
|
||||
try {
|
||||
Payment::where('status', 'open')->where('updated_at', '<', now()->subHour())->delete();
|
||||
} catch (\Exception $e) {
|
||||
$this->error('Could not delete payments: ' . $e->getMessage());
|
||||
return 1;
|
||||
}
|
||||
|
||||
$this->info('Successfully deleted all open payments');
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
}
|
43
app/Console/Commands/GetGithubVersion.php
Normal file
43
app/Console/Commands/GetGithubVersion.php
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class GetGithubVersion extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'cp:versioncheck:get';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Get the latest Version from Github';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
try{
|
||||
$latestVersion = Http::get('https://api.github.com/repos/ctrlpanel-gg/panel/tags')->json()[0]['name'];
|
||||
Storage::disk('local')->put('latestVersion', $latestVersion);
|
||||
} catch (Exception $e) {
|
||||
Storage::disk('local')->put('latestVersion', "unknown");
|
||||
Log::error($e);
|
||||
}
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
}
|
|
@ -12,6 +12,7 @@ class ImportUsersFromPteroCommand extends Command
|
|||
* @var string
|
||||
*/
|
||||
private $importFileName = 'users.json';
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
|
@ -39,25 +40,28 @@ class ImportUsersFromPteroCommand extends Command
|
|||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return boolean
|
||||
* @return bool
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
||||
//check if json file exists
|
||||
if (!Storage::disk('local')->exists('users.json')) {
|
||||
$this->error('[ERROR] ' . storage_path('app') . '/' . $this->importFileName . ' is missing');
|
||||
if (! Storage::disk('local')->exists('users.json')) {
|
||||
$this->error('[ERROR] '.storage_path('app').'/'.$this->importFileName.' is missing');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//check if json file is valid
|
||||
$json = json_decode(Storage::disk('local')->get('users.json'));
|
||||
if (!array_key_exists(2, $json)) {
|
||||
if (! array_key_exists(2, $json)) {
|
||||
$this->error('[ERROR] Invalid json file');
|
||||
|
||||
return false;
|
||||
}
|
||||
if (!$json[2]->data) {
|
||||
if (! $json[2]->data) {
|
||||
$this->error('[ERROR] Invalid json file / No users found!');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -69,12 +73,14 @@ class ImportUsersFromPteroCommand extends Command
|
|||
//cancel
|
||||
if ($confirm !== 'y') {
|
||||
$this->error('[ERROR] Stopped import script!');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//import users
|
||||
$this->deleteCurrentUserBase();
|
||||
$this->importUsingJsonFile($json, $initial_credits, $initial_server_limit);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -84,7 +90,9 @@ class ImportUsersFromPteroCommand extends Command
|
|||
private function deleteCurrentUserBase()
|
||||
{
|
||||
$currentUserCount = User::count();
|
||||
if ($currentUserCount == 0) return;
|
||||
if ($currentUserCount == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->line("Deleting ({$currentUserCount}) users..");
|
||||
foreach (User::all() as $user) {
|
||||
|
@ -104,20 +112,20 @@ class ImportUsersFromPteroCommand extends Command
|
|||
$role = $user->root_admin == '0' ? 'member' : 'admin';
|
||||
|
||||
User::create([
|
||||
"pterodactyl_id" => $user->id,
|
||||
"name" => $user->name_first,
|
||||
"email" => $user->email,
|
||||
"password" => $user->password,
|
||||
"role" => $role,
|
||||
"credits" => $initial_credits,
|
||||
"server_limit" => $initial_server_limit,
|
||||
"created_at" => $user->created_at,
|
||||
"updated_at" => $user->updated_at,
|
||||
'pterodactyl_id' => $user->id,
|
||||
'name' => $user->name_first,
|
||||
'email' => $user->email,
|
||||
'password' => $user->password,
|
||||
'role' => $role,
|
||||
'credits' => $initial_credits,
|
||||
'server_limit' => $initial_server_limit,
|
||||
'created_at' => $user->created_at,
|
||||
'updated_at' => $user->updated_at,
|
||||
]);
|
||||
});
|
||||
|
||||
$this->newLine();
|
||||
$this->line("Done importing, you can now login using your pterodactyl credentials.");
|
||||
$this->line('Done importing, you can now login using your pterodactyl credentials.');
|
||||
$this->newLine();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,13 +4,16 @@ namespace App\Console\Commands;
|
|||
|
||||
use App\Classes\Pterodactyl;
|
||||
use App\Models\User;
|
||||
use App\Traits\Referral;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class MakeUserCommand extends Command
|
||||
{
|
||||
use Referral;
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
|
@ -38,6 +41,7 @@ class MakeUserCommand extends Command
|
|||
$this->pterodactyl = $pterodactyl;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
|
@ -59,6 +63,7 @@ class MakeUserCommand extends Command
|
|||
|
||||
if ($validator->fails()) {
|
||||
$this->error($validator->errors()->first());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -66,18 +71,25 @@ class MakeUserCommand extends Command
|
|||
$response = $this->pterodactyl->getUser($ptero_id);
|
||||
|
||||
if (isset($response['errors'])) {
|
||||
if (isset($response['errors'][0]['code'])) $this->error("code: {$response['errors'][0]['code']}");
|
||||
if (isset($response['errors'][0]['status'])) $this->error("status: {$response['errors'][0]['status']}");
|
||||
if (isset($response['errors'][0]['detail'])) $this->error("detail: {$response['errors'][0]['detail']}");
|
||||
if (isset($response['errors'][0]['code'])) {
|
||||
$this->error("code: {$response['errors'][0]['code']}");
|
||||
}
|
||||
if (isset($response['errors'][0]['status'])) {
|
||||
$this->error("status: {$response['errors'][0]['status']}");
|
||||
}
|
||||
if (isset($response['errors'][0]['detail'])) {
|
||||
$this->error("detail: {$response['errors'][0]['detail']}");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
$user = User::create([
|
||||
'name' => $response['first_name'],
|
||||
'email' => $response['email'],
|
||||
'role' => 'admin',
|
||||
'password' => Hash::make($password),
|
||||
'pterodactyl_id' => $response['id']
|
||||
'referral_code' => $this->createReferralCode(),
|
||||
'pterodactyl_id' => $response['id'],
|
||||
]);
|
||||
|
||||
$this->table(['Field', 'Value'], [
|
||||
|
@ -86,6 +98,7 @@ class MakeUserCommand extends Command
|
|||
['Username', $user->name],
|
||||
['Ptero-ID', $user->pterodactyl_id],
|
||||
['Admin', $user->role],
|
||||
['Referral code', $user->referral_code],
|
||||
]);
|
||||
|
||||
return 1;
|
||||
|
|
|
@ -36,12 +36,13 @@ class notify extends Command
|
|||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @param int $id
|
||||
* @param int $id
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
User::findOrFail($this->argument('id'))->notify(new ServerCreationError(Server::all()[0]));
|
||||
|
||||
return 'message send';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Closure;
|
||||
use Symfony\Component\Process\Process;
|
||||
use Illuminate\Console\Command;
|
||||
use Symfony\Component\Console\Helper\ProgressBar;
|
||||
use Symfony\Component\Process\Process;
|
||||
|
||||
class update extends Command
|
||||
{
|
||||
|
@ -45,7 +45,7 @@ class update extends Command
|
|||
$this->output->warning('This command does just pull the newest changes from the github repo. Verify the github repo before running this');
|
||||
|
||||
if (version_compare(PHP_VERSION, '8.0.0') < 0) {
|
||||
$this->error('Cannot execute self-upgrade process. The minimum required PHP version required is 8.0.0, you have [' . PHP_VERSION . '].');
|
||||
$this->error('Cannot execute self-upgrade process. The minimum required PHP version required is 8.0.0, you have ['.PHP_VERSION.'].');
|
||||
}
|
||||
|
||||
$user = 'www-data';
|
||||
|
@ -55,7 +55,7 @@ class update extends Command
|
|||
$userDetails = posix_getpwuid(fileowner('public'));
|
||||
$user = $userDetails['name'] ?? 'www-data';
|
||||
|
||||
if (!$this->confirm("Your webserver user has been detected as [{$user}]: is this correct?", true)) {
|
||||
if (! $this->confirm("Your webserver user has been detected as [{$user}]: is this correct?", true)) {
|
||||
$user = $this->anticipate(
|
||||
'Please enter the name of the user running your webserver process. This varies from system to system, but is generally "www-data", "nginx", or "apache".',
|
||||
[
|
||||
|
@ -71,7 +71,7 @@ class update extends Command
|
|||
$groupDetails = posix_getgrgid(filegroup('public'));
|
||||
$group = $groupDetails['name'] ?? 'www-data';
|
||||
|
||||
if (!$this->confirm("Your webserver group has been detected as [{$group}]: is this correct?", true)) {
|
||||
if (! $this->confirm("Your webserver group has been detected as [{$group}]: is this correct?", true)) {
|
||||
$group = $this->anticipate(
|
||||
'Please enter the name of the group running your webserver process. Normally this is the same as your user.',
|
||||
[
|
||||
|
@ -85,24 +85,21 @@ class update extends Command
|
|||
|
||||
ini_set('output_buffering', 0);
|
||||
|
||||
if (!$this->confirm('Are you sure you want to run the upgrade process for your Dashboard?')) {
|
||||
if (! $this->confirm('Are you sure you want to run the upgrade process for your Dashboard?')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$bar = $this->output->createProgressBar(9);
|
||||
$bar->start();
|
||||
|
||||
|
||||
$this->withProgress($bar, function () {
|
||||
$this->line("\$upgrader> git pull");
|
||||
$process = Process::fromShellCommandline("git pull");
|
||||
$this->line('$upgrader> git pull');
|
||||
$process = Process::fromShellCommandline('git pull');
|
||||
$process->run(function ($type, $buffer) {
|
||||
$this->{$type === Process::ERR ? 'error' : 'line'}($buffer);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
$this->withProgress($bar, function () {
|
||||
$this->line('$upgrader> php artisan down');
|
||||
$this->call('down');
|
||||
|
@ -118,12 +115,12 @@ class update extends Command
|
|||
|
||||
$this->withProgress($bar, function () {
|
||||
$command = ['composer', 'install', '--no-ansi'];
|
||||
if (config('app.env') === 'production' && !config('app.debug')) {
|
||||
if (config('app.env') === 'production' && ! config('app.debug')) {
|
||||
$command[] = '--optimize-autoloader';
|
||||
$command[] = '--no-dev';
|
||||
}
|
||||
|
||||
$this->line('$upgrader> ' . implode(' ', $command));
|
||||
$this->line('$upgrader> '.implode(' ', $command));
|
||||
$process = new Process($command);
|
||||
$process->setTimeout(10 * 60);
|
||||
$process->run(function ($type, $buffer) {
|
||||
|
@ -162,10 +159,9 @@ class update extends Command
|
|||
|
||||
$this->newLine();
|
||||
$this->info('Finished running upgrade.');
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected function withProgress(ProgressBar $bar, Closure $callback)
|
||||
{
|
||||
$bar->clear();
|
||||
|
|
|
@ -8,28 +8,21 @@ use Illuminate\Support\Facades\Storage;
|
|||
|
||||
class Kernel extends ConsoleKernel
|
||||
{
|
||||
/**
|
||||
* The Artisan commands provided by your application.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $commands = [
|
||||
//
|
||||
];
|
||||
|
||||
/**
|
||||
* Define the application's command schedule.
|
||||
*
|
||||
* @param \Illuminate\Console\Scheduling\Schedule $schedule
|
||||
* @param \Illuminate\Console\Scheduling\Schedule $schedule
|
||||
* @return void
|
||||
*/
|
||||
protected function schedule(Schedule $schedule)
|
||||
{
|
||||
$schedule->command('credits:charge')->hourly();
|
||||
$schedule->command('cp:versioncheck:get')->daily();
|
||||
$schedule->command('payments:open:clear')->daily();
|
||||
|
||||
//log cronjob activity
|
||||
$schedule->call(function () {
|
||||
Storage::disk('logs')->put('cron.log' , "Last activity from cronjobs - " . now());
|
||||
Storage::disk('logs')->put('cron.log', 'Last activity from cronjobs - ' . now());
|
||||
})->everyMinute();
|
||||
}
|
||||
|
||||
|
|
19
app/Enums/UsefulLinkLocation.php
Normal file
19
app/Enums/UsefulLinkLocation.php
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
enum UsefulLinkLocation:String
|
||||
{
|
||||
/**
|
||||
* Top bar
|
||||
* Only visible in the dashboard view
|
||||
*/
|
||||
case topbar = "topbar";
|
||||
|
||||
/**
|
||||
* Dashboard
|
||||
* Only visible in the dashboard view
|
||||
*/
|
||||
case dashboard = "dashboard";
|
||||
|
||||
}
|
31
app/Events/PaymentEvent.php
Normal file
31
app/Events/PaymentEvent.php
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Models\Payment;
|
||||
use App\Models\ShopProduct;
|
||||
use App\Models\User;
|
||||
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class PaymentEvent
|
||||
{
|
||||
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||
|
||||
public User $user;
|
||||
public Payment $payment;
|
||||
public ShopProduct $shopProduct;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(User $user, Payment $payment, ShopProduct $shopProduct)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->payment = $payment;
|
||||
$this->shopProduct = $shopProduct;
|
||||
}
|
||||
}
|
|
@ -3,11 +3,7 @@
|
|||
namespace App\Events;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Broadcasting\Channel;
|
||||
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||
use Illuminate\Broadcasting\PresenceChannel;
|
||||
use Illuminate\Broadcasting\PrivateChannel;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
|
@ -23,7 +19,7 @@ class UserUpdateCreditsEvent
|
|||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param User $user
|
||||
* @param User $user
|
||||
*/
|
||||
public function __construct(User $user)
|
||||
{
|
||||
|
|
|
@ -7,21 +7,31 @@ use Throwable;
|
|||
|
||||
class Handler extends ExceptionHandler
|
||||
{
|
||||
/**
|
||||
* A list of exception types with their corresponding custom log levels.
|
||||
*
|
||||
* @var array<class-string<\Throwable>, \Psr\Log\LogLevel::*>
|
||||
*/
|
||||
protected $levels = [
|
||||
//
|
||||
];
|
||||
|
||||
/**
|
||||
* A list of the exception types that are not reported.
|
||||
*
|
||||
* @var array
|
||||
* @var array<int, class-string<\Throwable>>
|
||||
*/
|
||||
protected $dontReport = [
|
||||
//
|
||||
];
|
||||
|
||||
/**
|
||||
* A list of the inputs that are never flashed for validation exceptions.
|
||||
* A list of the inputs that are never flashed to the session on validation exceptions.
|
||||
*
|
||||
* @var array
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $dontFlash = [
|
||||
'current_password',
|
||||
'password',
|
||||
'password_confirmation',
|
||||
];
|
||||
|
|
13
app/Extensions/PaymentGateways/PayPal/config.php
Normal file
13
app/Extensions/PaymentGateways/PayPal/config.php
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace App\Extensions\PaymentGateways\PayPal;
|
||||
|
||||
function getConfig()
|
||||
{
|
||||
return [
|
||||
"name" => "PayPal",
|
||||
"description" => "PayPal payment gateway",
|
||||
"RoutesIgnoreCsrf" => [],
|
||||
"enabled" => (config('SETTINGS::PAYMENTS:PAYPAL:SECRET') && config('SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID')) || (config('SETTINGS::PAYMENTS:PAYPAL:SANDBOX_SECRET') && config('SETTINGS::PAYMENTS:PAYPAL:SANDBOX_CLIENT_ID') && env("APP_ENV") === "local"),
|
||||
];
|
||||
}
|
186
app/Extensions/PaymentGateways/PayPal/index.php
Normal file
186
app/Extensions/PaymentGateways/PayPal/index.php
Normal file
|
@ -0,0 +1,186 @@
|
|||
<?php
|
||||
|
||||
use App\Events\PaymentEvent;
|
||||
use App\Events\UserUpdateCreditsEvent;
|
||||
use App\Models\PartnerDiscount;
|
||||
use App\Models\Payment;
|
||||
use App\Models\ShopProduct;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Redirect;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use PayPalCheckoutSdk\Core\PayPalHttpClient;
|
||||
use PayPalCheckoutSdk\Core\ProductionEnvironment;
|
||||
use PayPalCheckoutSdk\Core\SandboxEnvironment;
|
||||
use PayPalCheckoutSdk\Orders\OrdersCaptureRequest;
|
||||
use PayPalCheckoutSdk\Orders\OrdersCreateRequest;
|
||||
use PayPalHttp\HttpException;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param ShopProduct $shopProduct
|
||||
*/
|
||||
function PaypalPay(Request $request)
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = Auth::user();
|
||||
$shopProduct = ShopProduct::findOrFail($request->shopProduct);
|
||||
$discount = PartnerDiscount::getDiscount();
|
||||
|
||||
// create a new payment
|
||||
$payment = Payment::create([
|
||||
'user_id' => $user->id,
|
||||
'payment_id' => null,
|
||||
'payment_method' => 'paypal',
|
||||
'type' => $shopProduct->type,
|
||||
'status' => 'open',
|
||||
'amount' => $shopProduct->quantity,
|
||||
'price' => $shopProduct->price - ($shopProduct->price * $discount / 100),
|
||||
'tax_value' => $shopProduct->getTaxValue(),
|
||||
'tax_percent' => $shopProduct->getTaxPercent(),
|
||||
'total_price' => $shopProduct->getTotalPrice(),
|
||||
'currency_code' => $shopProduct->currency_code,
|
||||
'shop_item_product_id' => $shopProduct->id,
|
||||
]);
|
||||
|
||||
$request = new OrdersCreateRequest();
|
||||
$request->prefer('return=representation');
|
||||
$request->body = [
|
||||
"intent" => "CAPTURE",
|
||||
"purchase_units" => [
|
||||
[
|
||||
"reference_id" => uniqid(),
|
||||
"description" => $shopProduct->display . ($discount ? (" (" . __('Discount') . " " . $discount . '%)') : ""),
|
||||
"amount" => [
|
||||
"value" => $shopProduct->getTotalPrice(),
|
||||
'currency_code' => strtoupper($shopProduct->currency_code),
|
||||
'breakdown' => [
|
||||
'item_total' =>
|
||||
[
|
||||
'currency_code' => strtoupper($shopProduct->currency_code),
|
||||
'value' => $shopProduct->getPriceAfterDiscount(),
|
||||
],
|
||||
'tax_total' =>
|
||||
[
|
||||
'currency_code' => strtoupper($shopProduct->currency_code),
|
||||
'value' => $shopProduct->getTaxValue(),
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
"application_context" => [
|
||||
"cancel_url" => route('payment.Cancel'),
|
||||
"return_url" => route('payment.PayPalSuccess', ['payment' => $payment->id]),
|
||||
'brand_name' => config('app.name', 'CtrlPanel.gg'),
|
||||
'shipping_preference' => 'NO_SHIPPING'
|
||||
]
|
||||
|
||||
|
||||
];
|
||||
|
||||
try {
|
||||
// Call API with your client and get a response for your call
|
||||
$response = getPayPalClient()->execute($request);
|
||||
|
||||
// check for any errors in the response
|
||||
if ($response->statusCode != 201) {
|
||||
throw new \Exception($response->statusCode);
|
||||
}
|
||||
|
||||
// make sure the link is not empty
|
||||
if (empty($response->result->links[1]->href)) {
|
||||
throw new \Exception('No redirect link found');
|
||||
}
|
||||
|
||||
Redirect::away($response->result->links[1]->href)->send();
|
||||
return;
|
||||
} catch (HttpException $ex) {
|
||||
Log::error('PayPal Payment: ' . $ex->getMessage());
|
||||
$payment->delete();
|
||||
|
||||
Redirect::route('store.index')->with('error', __('Payment failed'))->send();
|
||||
return;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param Request $laravelRequest
|
||||
*/
|
||||
function PaypalSuccess(Request $laravelRequest)
|
||||
{
|
||||
$user = Auth::user();
|
||||
$user = User::findOrFail($user->id);
|
||||
|
||||
$payment = Payment::findOrFail($laravelRequest->payment);
|
||||
$shopProduct = ShopProduct::findOrFail($payment->shop_item_product_id);
|
||||
|
||||
$request = new OrdersCaptureRequest($laravelRequest->input('token'));
|
||||
$request->prefer('return=representation');
|
||||
|
||||
try {
|
||||
// Call API with your client and get a response for your call
|
||||
$response = getPayPalClient()->execute($request);
|
||||
if ($response->statusCode == 201 || $response->statusCode == 200) {
|
||||
//update payment
|
||||
$payment->update([
|
||||
'status' => 'paid',
|
||||
'payment_id' => $response->result->id,
|
||||
]);
|
||||
|
||||
event(new UserUpdateCreditsEvent($user));
|
||||
event(new PaymentEvent($user, $payment, $shopProduct));
|
||||
|
||||
// redirect to the payment success page with success message
|
||||
Redirect::route('home')->with('success', 'Payment successful')->send();
|
||||
} elseif (env('APP_ENV') == 'local') {
|
||||
// If call returns body in response, you can get the deserialized version from the result attribute of the response
|
||||
$payment->delete();
|
||||
dd($response);
|
||||
} else {
|
||||
$payment->update([
|
||||
'status' => 'cancelled',
|
||||
'payment_id' => $response->result->id,
|
||||
]);
|
||||
abort(500);
|
||||
}
|
||||
} catch (HttpException $ex) {
|
||||
if (env('APP_ENV') == 'local') {
|
||||
echo $ex->statusCode;
|
||||
$payment->delete();
|
||||
dd($ex->getMessage());
|
||||
} else {
|
||||
$payment->update([
|
||||
'status' => 'cancelled',
|
||||
'payment_id' => $response->result->id,
|
||||
]);
|
||||
abort(422);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @return PayPalHttpClient
|
||||
*/
|
||||
function getPayPalClient()
|
||||
{
|
||||
$environment = env('APP_ENV') == 'local'
|
||||
? new SandboxEnvironment(getPaypalClientId(), getPaypalClientSecret())
|
||||
: new ProductionEnvironment(getPaypalClientId(), getPaypalClientSecret());
|
||||
return new PayPalHttpClient($environment);
|
||||
}
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
function getPaypalClientId()
|
||||
{
|
||||
return env('APP_ENV') == 'local' ? config("SETTINGS::PAYMENTS:PAYPAL:SANDBOX_CLIENT_ID") : config("SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID");
|
||||
}
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
function getPaypalClientSecret()
|
||||
{
|
||||
return env('APP_ENV') == 'local' ? config("SETTINGS::PAYMENTS:PAYPAL:SANDBOX_SECRET") : config("SETTINGS::PAYMENTS:PAYPAL:SECRET");
|
||||
}
|
18
app/Extensions/PaymentGateways/PayPal/web_routes.php
Normal file
18
app/Extensions/PaymentGateways/PayPal/web_routes.php
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
include_once(__DIR__ . '/index.php');
|
||||
|
||||
Route::middleware(['web', 'auth'])->group(function () {
|
||||
Route::get('payment/PayPalPay/{shopProduct}', function () {
|
||||
PaypalPay(request());
|
||||
})->name('payment.PayPalPay');
|
||||
|
||||
Route::get(
|
||||
'payment/PayPalSuccess',
|
||||
function () {
|
||||
PaypalSuccess(request());
|
||||
}
|
||||
)->name('payment.PayPalSuccess');
|
||||
});
|
15
app/Extensions/PaymentGateways/Stripe/config.php
Normal file
15
app/Extensions/PaymentGateways/Stripe/config.php
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
namespace App\Extensions\PaymentGateways\Stripe;
|
||||
|
||||
function getConfig()
|
||||
{
|
||||
return [
|
||||
"name" => "Stripe",
|
||||
"description" => "Stripe payment gateway",
|
||||
"RoutesIgnoreCsrf" => [
|
||||
"payment/StripeWebhooks",
|
||||
],
|
||||
"enabled" => config('SETTINGS::PAYMENTS:STRIPE:SECRET') && config('SETTINGS::PAYMENTS:STRIPE:ENDPOINT_SECRET') || config('SETTINGS::PAYMENTS:STRIPE:ENDPOINT_TEST_SECRET') && config('SETTINGS::PAYMENTS:STRIPE:TEST_SECRET') && env("APP_ENV") === "local",
|
||||
];
|
||||
}
|
373
app/Extensions/PaymentGateways/Stripe/index.php
Normal file
373
app/Extensions/PaymentGateways/Stripe/index.php
Normal file
|
@ -0,0 +1,373 @@
|
|||
<?php
|
||||
|
||||
use App\Events\PaymentEvent;
|
||||
use App\Events\UserUpdateCreditsEvent;
|
||||
use App\Models\PartnerDiscount;
|
||||
use App\Models\Payment;
|
||||
use App\Models\ShopProduct;
|
||||
use App\Models\User;
|
||||
use App\Notifications\ConfirmPaymentNotification;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Redirect;
|
||||
use Stripe\Exception\SignatureVerificationException;
|
||||
use Stripe\Stripe;
|
||||
use Stripe\StripeClient;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param ShopProduct $shopProduct
|
||||
*/
|
||||
function StripePay(Request $request)
|
||||
{
|
||||
$user = Auth::user();
|
||||
$shopProduct = ShopProduct::findOrFail($request->shopProduct);
|
||||
|
||||
// check if the price is valid for stripe
|
||||
if (!checkPriceAmount($shopProduct->getTotalPrice(), strtoupper($shopProduct->currency_code), 'stripe')) {
|
||||
Redirect::route('home')->with('error', __('The product you chose can\'t be purchased with this payment method. The total amount is too small. Please buy a bigger amount or try a different payment method.'))->send();
|
||||
return;
|
||||
}
|
||||
|
||||
$discount = PartnerDiscount::getDiscount();
|
||||
|
||||
|
||||
// create payment
|
||||
$payment = Payment::create([
|
||||
'user_id' => $user->id,
|
||||
'payment_id' => null,
|
||||
'payment_method' => 'stripe',
|
||||
'type' => $shopProduct->type,
|
||||
'status' => 'open',
|
||||
'amount' => $shopProduct->quantity,
|
||||
'price' => $shopProduct->price - ($shopProduct->price * $discount / 100),
|
||||
'tax_value' => $shopProduct->getTaxValue(),
|
||||
'total_price' => $shopProduct->getTotalPrice(),
|
||||
'tax_percent' => $shopProduct->getTaxPercent(),
|
||||
'currency_code' => $shopProduct->currency_code,
|
||||
'shop_item_product_id' => $shopProduct->id,
|
||||
]);
|
||||
|
||||
$stripeClient = getStripeClient();
|
||||
$request = $stripeClient->checkout->sessions->create([
|
||||
'line_items' => [
|
||||
[
|
||||
'price_data' => [
|
||||
'currency' => $shopProduct->currency_code,
|
||||
'product_data' => [
|
||||
'name' => $shopProduct->display . ($discount ? (' (' . __('Discount') . ' ' . $discount . '%)') : ''),
|
||||
'description' => $shopProduct->description,
|
||||
],
|
||||
'unit_amount_decimal' => round($shopProduct->getPriceAfterDiscount() * 100, 2),
|
||||
],
|
||||
'quantity' => 1,
|
||||
],
|
||||
[
|
||||
'price_data' => [
|
||||
'currency' => $shopProduct->currency_code,
|
||||
'product_data' => [
|
||||
'name' => __('Tax'),
|
||||
'description' => $shopProduct->getTaxPercent() . '%',
|
||||
],
|
||||
'unit_amount_decimal' => round($shopProduct->getTaxValue(), 2) * 100,
|
||||
],
|
||||
'quantity' => 1,
|
||||
],
|
||||
],
|
||||
|
||||
'mode' => 'payment',
|
||||
'payment_method_types' => str_getcsv(config('SETTINGS::PAYMENTS:STRIPE:METHODS')),
|
||||
'success_url' => route('payment.StripeSuccess', ['payment' => $payment->id]) . '&session_id={CHECKOUT_SESSION_ID}',
|
||||
'cancel_url' => route('payment.Cancel'),
|
||||
'payment_intent_data' => [
|
||||
'metadata' => [
|
||||
'payment_id' => $payment->id,
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
Redirect::to($request->url)->send();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
*/
|
||||
function StripeSuccess(Request $request)
|
||||
{
|
||||
$user = Auth::user();
|
||||
$user = User::findOrFail($user->id);
|
||||
$payment = Payment::findOrFail($request->input('payment'));
|
||||
$shopProduct = ShopProduct::findOrFail($payment->shop_item_product_id);
|
||||
|
||||
|
||||
Redirect::route('home')->with('success', 'Please wait for success')->send();
|
||||
|
||||
$stripeClient = getStripeClient();
|
||||
try {
|
||||
//get stripe data
|
||||
$paymentSession = $stripeClient->checkout->sessions->retrieve($request->input('session_id'));
|
||||
$paymentIntent = $stripeClient->paymentIntents->retrieve($paymentSession->payment_intent);
|
||||
|
||||
//get DB entry of this payment ID if existing
|
||||
$paymentDbEntry = Payment::where('payment_id', $paymentSession->payment_intent)->count();
|
||||
|
||||
// check if payment is 100% completed and payment does not exist in db already
|
||||
if ($paymentSession->status == 'complete' && $paymentIntent->status == 'succeeded' && $paymentDbEntry == 0) {
|
||||
|
||||
//update payment
|
||||
$payment->update([
|
||||
'payment_id' => $paymentSession->payment_intent,
|
||||
'status' => 'paid',
|
||||
]);
|
||||
|
||||
//payment notification
|
||||
$user->notify(new ConfirmPaymentNotification($payment));
|
||||
|
||||
event(new UserUpdateCreditsEvent($user));
|
||||
event(new PaymentEvent($user, $payment, $shopProduct));
|
||||
|
||||
//redirect back to home
|
||||
Redirect::route('home')->with('success', 'Payment successful')->send();
|
||||
} else {
|
||||
if ($paymentIntent->status == 'processing') {
|
||||
|
||||
//update payment
|
||||
$payment->update([
|
||||
'payment_id' => $paymentSession->payment_intent,
|
||||
'status' => 'processing',
|
||||
]);
|
||||
|
||||
event(new PaymentEvent($user, $payment, $shopProduct));
|
||||
|
||||
Redirect::route('home')->with('success', 'Your payment is being processed')->send();
|
||||
}
|
||||
|
||||
if ($paymentDbEntry == 0 && $paymentIntent->status != 'processing') {
|
||||
$stripeClient->paymentIntents->cancel($paymentIntent->id);
|
||||
|
||||
//redirect back to home
|
||||
Redirect::route('home')->with('info', __('Your payment has been canceled!'))->send();
|
||||
} else {
|
||||
abort(402);
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
if (env('APP_ENV') == 'local') {
|
||||
dd($e->getMessage());
|
||||
} else {
|
||||
abort(422);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
*/
|
||||
function handleStripePaymentSuccessHook($paymentIntent)
|
||||
{
|
||||
try {
|
||||
$payment = Payment::where('id', $paymentIntent->metadata->payment_id)->with('user')->first();
|
||||
$user = User::where('id', $payment->user_id)->first();
|
||||
$shopProduct = ShopProduct::findOrFail($payment->shop_item_product_id);
|
||||
|
||||
if ($paymentIntent->status == 'succeeded' && $payment->status == 'processing') {
|
||||
|
||||
//update payment db entry status
|
||||
$payment->update([
|
||||
'payment_id' => $payment->payment_id ?? $paymentIntent->id,
|
||||
'status' => 'paid'
|
||||
]);
|
||||
|
||||
//payment notification
|
||||
$user->notify(new ConfirmPaymentNotification($payment));
|
||||
event(new UserUpdateCreditsEvent($user));
|
||||
event(new PaymentEvent($user, $payment, $shopProduct));
|
||||
}
|
||||
|
||||
// return 200
|
||||
return response()->json(['success' => true], 200);
|
||||
} catch (Exception $ex) {
|
||||
abort(422);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
*/
|
||||
function StripeWebhooks(Request $request)
|
||||
{
|
||||
Stripe::setApiKey(getStripeSecret());
|
||||
|
||||
try {
|
||||
$payload = @file_get_contents('php://input');
|
||||
$sig_header = $request->header('Stripe-Signature');
|
||||
$event = null;
|
||||
$event = \Stripe\Webhook::constructEvent(
|
||||
$payload,
|
||||
$sig_header,
|
||||
getStripeEndpointSecret()
|
||||
);
|
||||
} catch (\UnexpectedValueException $e) {
|
||||
// Invalid payload
|
||||
|
||||
abort(400);
|
||||
} catch (SignatureVerificationException $e) {
|
||||
// Invalid signature
|
||||
|
||||
abort(400);
|
||||
}
|
||||
|
||||
// Handle the event
|
||||
switch ($event->type) {
|
||||
case 'payment_intent.succeeded':
|
||||
$paymentIntent = $event->data->object; // contains a \Stripe\PaymentIntent
|
||||
handleStripePaymentSuccessHook($paymentIntent);
|
||||
break;
|
||||
default:
|
||||
echo 'Received unknown event type ' . $event->type;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Stripe\StripeClient
|
||||
*/
|
||||
function getStripeClient()
|
||||
{
|
||||
return new StripeClient(getStripeSecret());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
function getStripeSecret()
|
||||
{
|
||||
return env('APP_ENV') == 'local'
|
||||
? config('SETTINGS::PAYMENTS:STRIPE:TEST_SECRET')
|
||||
: config('SETTINGS::PAYMENTS:STRIPE:SECRET');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
function getStripeEndpointSecret()
|
||||
{
|
||||
return env('APP_ENV') == 'local'
|
||||
? config('SETTINGS::PAYMENTS:STRIPE:ENDPOINT_TEST_SECRET')
|
||||
: config('SETTINGS::PAYMENTS:STRIPE:ENDPOINT_SECRET');
|
||||
}
|
||||
/**
|
||||
* @param $amount
|
||||
* @param $currencyCode
|
||||
* @param $payment_method
|
||||
* @return bool
|
||||
* @description check if the amount is higher than the minimum amount for the stripe gateway
|
||||
*/
|
||||
function checkPriceAmount($amount, $currencyCode, $payment_method)
|
||||
{
|
||||
$minimums = [
|
||||
"USD" => [
|
||||
"paypal" => 0,
|
||||
"stripe" => 0.5
|
||||
],
|
||||
"AED" => [
|
||||
"paypal" => 0,
|
||||
"stripe" => 2
|
||||
],
|
||||
"AUD" => [
|
||||
"paypal" => 0,
|
||||
"stripe" => 0.5
|
||||
],
|
||||
"BGN" => [
|
||||
"paypal" => 0,
|
||||
"stripe" => 1
|
||||
],
|
||||
"BRL" => [
|
||||
"paypal" => 0,
|
||||
"stripe" => 0.5
|
||||
],
|
||||
"CAD" => [
|
||||
"paypal" => 0,
|
||||
"stripe" => 0.5
|
||||
],
|
||||
"CHF" => [
|
||||
"paypal" => 0,
|
||||
"stripe" => 0.5
|
||||
],
|
||||
"CZK" => [
|
||||
"paypal" => 0,
|
||||
"stripe" => 15
|
||||
],
|
||||
"DKK" => [
|
||||
"paypal" => 0,
|
||||
"stripe" => 2.5
|
||||
],
|
||||
"EUR" => [
|
||||
"paypal" => 0,
|
||||
"stripe" => 0.5
|
||||
],
|
||||
"GBP" => [
|
||||
"paypal" => 0,
|
||||
"stripe" => 0.3
|
||||
],
|
||||
"HKD" => [
|
||||
"paypal" => 0,
|
||||
"stripe" => 4
|
||||
],
|
||||
"HRK" => [
|
||||
"paypal" => 0,
|
||||
"stripe" => 0.5
|
||||
],
|
||||
"HUF" => [
|
||||
"paypal" => 0,
|
||||
"stripe" => 175
|
||||
],
|
||||
"INR" => [
|
||||
"paypal" => 0,
|
||||
"stripe" => 0.5
|
||||
],
|
||||
"JPY" => [
|
||||
"paypal" => 0,
|
||||
"stripe" => 0.5
|
||||
],
|
||||
"MXN" => [
|
||||
"paypal" => 0,
|
||||
"stripe" => 10
|
||||
],
|
||||
"MYR" => [
|
||||
"paypal" => 0,
|
||||
"stripe" => 2
|
||||
],
|
||||
"NOK" => [
|
||||
"paypal" => 0,
|
||||
"stripe" => 3
|
||||
],
|
||||
"NZD" => [
|
||||
"paypal" => 0,
|
||||
"stripe" => 0.5
|
||||
],
|
||||
"PLN" => [
|
||||
"paypal" => 0,
|
||||
"stripe" => 2
|
||||
],
|
||||
"RON" => [
|
||||
"paypal" => 0,
|
||||
"stripe" => 2
|
||||
],
|
||||
"SEK" => [
|
||||
"paypal" => 0,
|
||||
"stripe" => 3
|
||||
],
|
||||
"SGD" => [
|
||||
"paypal" => 0,
|
||||
"stripe" => 0.5
|
||||
],
|
||||
"THB" => [
|
||||
"paypal" => 0,
|
||||
"stripe" => 10
|
||||
]
|
||||
];
|
||||
return $amount >= $minimums[$currencyCode][$payment_method];
|
||||
}
|
23
app/Extensions/PaymentGateways/Stripe/web_routes.php
Normal file
23
app/Extensions/PaymentGateways/Stripe/web_routes.php
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
include_once(__DIR__ . '/index.php');
|
||||
Route::middleware(['web', 'auth'])->group(function () {
|
||||
Route::get('payment/StripePay/{shopProduct}', function () {
|
||||
StripePay(request());
|
||||
})->name('payment.StripePay');
|
||||
|
||||
Route::get(
|
||||
'payment/StripeSuccess',
|
||||
function () {
|
||||
StripeSuccess(request());
|
||||
}
|
||||
)->name('payment.StripeSuccess');
|
||||
});
|
||||
|
||||
|
||||
// Stripe WebhookRoute -> validation in Route Handler
|
||||
Route::post('payment/StripeWebhooks', function () {
|
||||
StripeWebhooks(request());
|
||||
})->name('payment.StripeWebhooks');
|
82
app/Helpers/ExtensionHelper.php
Normal file
82
app/Helpers/ExtensionHelper.php
Normal file
|
@ -0,0 +1,82 @@
|
|||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
class ExtensionHelper
|
||||
{
|
||||
/**
|
||||
* Get a config of an extension by its name
|
||||
* @param string $extensionName
|
||||
* @param string $configname
|
||||
*/
|
||||
public static function getExtensionConfig(string $extensionName, string $configname)
|
||||
{
|
||||
$extensions = ExtensionHelper::getAllExtensions();
|
||||
|
||||
// call the getConfig function of the config file of the extension like that
|
||||
// call_user_func("App\\Extensions\\PaymentGateways\\Stripe" . "\\getConfig");
|
||||
foreach ($extensions as $extension) {
|
||||
if (!(basename($extension) == $extensionName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$configFile = $extension . '/config.php';
|
||||
if (file_exists($configFile)) {
|
||||
include_once $configFile;
|
||||
$config = call_user_func('App\\Extensions\\' . basename(dirname($extension)) . '\\' . basename($extension) . "\\getConfig");
|
||||
}
|
||||
|
||||
|
||||
if (isset($config[$configname])) {
|
||||
return $config[$configname];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function getAllCsrfIgnoredRoutes()
|
||||
{
|
||||
$extensions = ExtensionHelper::getAllExtensions();
|
||||
|
||||
$routes = [];
|
||||
foreach ($extensions as $extension) {
|
||||
$configFile = $extension . '/config.php';
|
||||
if (file_exists($configFile)) {
|
||||
include_once $configFile;
|
||||
$config = call_user_func('App\\Extensions\\' . basename(dirname($extension)) . '\\' . basename($extension) . "\\getConfig");
|
||||
}
|
||||
|
||||
if (isset($config['RoutesIgnoreCsrf'])) {
|
||||
$routes = array_merge($routes, $config['RoutesIgnoreCsrf']);
|
||||
}
|
||||
|
||||
// map over the routes and add the extension name as prefix
|
||||
$result = array_map(fn ($item) => "extensions/{$item}", $routes);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all extensions
|
||||
* @return array
|
||||
*/
|
||||
public static function getAllExtensions()
|
||||
{
|
||||
$extensionNamespaces = glob(app_path() . '/Extensions/*', GLOB_ONLYDIR);
|
||||
$extensions = [];
|
||||
foreach ($extensionNamespaces as $extensionNamespace) {
|
||||
$extensions = array_merge($extensions, glob($extensionNamespace . '/*', GLOB_ONLYDIR));
|
||||
}
|
||||
|
||||
return $extensions;
|
||||
}
|
||||
|
||||
public static function getAllExtensionsByNamespace(string $namespace)
|
||||
{
|
||||
$extensions = glob(app_path() . '/Extensions/' . $namespace . '/*', GLOB_ONLYDIR);
|
||||
|
||||
return $extensions;
|
||||
}
|
||||
}
|
|
@ -24,17 +24,16 @@ class ActivityLogController extends Controller
|
|||
$cronLogs = Storage::disk('logs')->exists('cron.log') ? Storage::disk('logs')->get('cron.log') : null;
|
||||
|
||||
if ($request->input('search')) {
|
||||
$query = Activity::whereHasMorph('causer' , [User::class] , function($query) use ($request) {
|
||||
$query->where('name', 'like' , "%{$request->input('search')}%");
|
||||
})->orderBy('created_at' , 'desc')->paginate(20);
|
||||
$query = Activity::whereHasMorph('causer', [User::class], function ($query) use ($request) {
|
||||
$query->where('name', 'like', "%{$request->input('search')}%");
|
||||
})->orderBy('created_at', 'desc')->paginate(20);
|
||||
} else {
|
||||
$query = Activity::orderBy('created_at' , 'desc')->paginate(20);
|
||||
$query = Activity::orderBy('created_at', 'desc')->paginate(20);
|
||||
}
|
||||
|
||||
|
||||
return view('admin.activitylogs.index')->with([
|
||||
'logs' => $query,
|
||||
'cronlogs' => $cronLogs
|
||||
'cronlogs' => $cronLogs,
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -51,7 +50,7 @@ class ActivityLogController extends Controller
|
|||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
|
@ -84,7 +83,7 @@ class ActivityLogController extends Controller
|
|||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Request $request
|
||||
* @param int $id
|
||||
* @return Response
|
||||
*/
|
||||
|
|
|
@ -12,7 +12,6 @@ use Illuminate\Http\JsonResponse;
|
|||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class ApplicationApiController extends Controller
|
||||
{
|
||||
|
@ -39,17 +38,17 @@ class ApplicationApiController extends Controller
|
|||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Request $request
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'memo' => 'nullable|string|max:60'
|
||||
'memo' => 'nullable|string|max:60',
|
||||
]);
|
||||
|
||||
ApplicationApi::create([
|
||||
'memo' => $request->input('memo')
|
||||
'memo' => $request->input('memo'),
|
||||
]);
|
||||
|
||||
return redirect()->route('admin.api.index')->with('success', __('api key created!'));
|
||||
|
@ -58,7 +57,7 @@ class ApplicationApiController extends Controller
|
|||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param ApplicationApi $applicationApi
|
||||
* @param ApplicationApi $applicationApi
|
||||
* @return Response
|
||||
*/
|
||||
public function show(ApplicationApi $applicationApi)
|
||||
|
@ -69,27 +68,27 @@ class ApplicationApiController extends Controller
|
|||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param ApplicationApi $applicationApi
|
||||
* @param ApplicationApi $applicationApi
|
||||
* @return Application|Factory|View|Response
|
||||
*/
|
||||
public function edit(ApplicationApi $applicationApi)
|
||||
{
|
||||
return view('admin.api.edit' , [
|
||||
'applicationApi' => $applicationApi
|
||||
return view('admin.api.edit', [
|
||||
'applicationApi' => $applicationApi,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param ApplicationApi $applicationApi
|
||||
* @param Request $request
|
||||
* @param ApplicationApi $applicationApi
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function update(Request $request, ApplicationApi $applicationApi)
|
||||
{
|
||||
$request->validate([
|
||||
'memo' => 'nullable|string|max:60'
|
||||
'memo' => 'nullable|string|max:60',
|
||||
]);
|
||||
|
||||
$applicationApi->update($request->all());
|
||||
|
@ -100,18 +99,20 @@ class ApplicationApiController extends Controller
|
|||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param ApplicationApi $applicationApi
|
||||
* @param ApplicationApi $applicationApi
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function destroy(ApplicationApi $applicationApi)
|
||||
{
|
||||
$applicationApi->delete();
|
||||
|
||||
return redirect()->back()->with('success', __('api key has been removed!'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Request $request
|
||||
* @return JsonResponse|mixed
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function dataTable(Request $request)
|
||||
|
@ -121,21 +122,21 @@ class ApplicationApiController extends Controller
|
|||
return datatables($query)
|
||||
->addColumn('actions', function (ApplicationApi $apiKey) {
|
||||
return '
|
||||
<a data-content="'.__("Edit").'" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.api.edit', $apiKey->token) . '" class="btn btn-sm btn-info mr-1"><i class="fas fa-pen"></i></a>
|
||||
<form class="d-inline" onsubmit="return submitResult();" method="post" action="' . route('admin.api.destroy', $apiKey->token) . '">
|
||||
' . csrf_field() . '
|
||||
' . method_field("DELETE") . '
|
||||
<button data-content="'.__("Delete").'" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm btn-danger mr-1"><i class="fas fa-trash"></i></button>
|
||||
<a data-content="'.__('Edit').'" data-toggle="popover" data-trigger="hover" data-placement="top" href="'.route('admin.api.edit', $apiKey->token).'" class="btn btn-sm btn-info mr-1"><i class="fas fa-pen"></i></a>
|
||||
<form class="d-inline" onsubmit="return submitResult();" method="post" action="'.route('admin.api.destroy', $apiKey->token).'">
|
||||
'.csrf_field().'
|
||||
'.method_field('DELETE').'
|
||||
<button data-content="'.__('Delete').'" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm btn-danger mr-1"><i class="fas fa-trash"></i></button>
|
||||
</form>
|
||||
';
|
||||
})
|
||||
->editColumn('token' , function (ApplicationApi $apiKey) {
|
||||
->editColumn('token', function (ApplicationApi $apiKey) {
|
||||
return "<code>{$apiKey->token}</code>";
|
||||
})
|
||||
->editColumn('last_used' , function (ApplicationApi $apiKey) {
|
||||
->editColumn('last_used', function (ApplicationApi $apiKey) {
|
||||
return $apiKey->last_used ? $apiKey->last_used->diffForHumans() : '';
|
||||
})
|
||||
->rawColumns(['actions' , 'token'])
|
||||
->rawColumns(['actions', 'token'])
|
||||
->make();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,15 +10,14 @@ use ZipArchive;
|
|||
|
||||
class InvoiceController extends Controller
|
||||
{
|
||||
|
||||
public function downloadAllInvoices()
|
||||
{
|
||||
$zip = new ZipArchive;
|
||||
$zip_safe_path = storage_path('invoices.zip');
|
||||
$res = $zip->open($zip_safe_path, ZipArchive::CREATE | ZipArchive::OVERWRITE);
|
||||
$result = $this::rglob(storage_path('app/invoice/*'));
|
||||
if ($res === TRUE) {
|
||||
$zip->addFromString("1. Info.txt", __("Created at") . " " . now()->format("d.m.Y"));
|
||||
if ($res === true) {
|
||||
$zip->addFromString('1. Info.txt', __('Created at').' '.now()->format('d.m.Y'));
|
||||
foreach ($result as $file) {
|
||||
if (file_exists($file) && is_file($file)) {
|
||||
$zip->addFile($file, basename($file));
|
||||
|
@ -26,6 +25,7 @@ class InvoiceController extends Controller
|
|||
}
|
||||
$zip->close();
|
||||
}
|
||||
|
||||
return response()->download($zip_safe_path);
|
||||
}
|
||||
|
||||
|
@ -37,9 +37,10 @@ class InvoiceController extends Controller
|
|||
public function rglob($pattern, $flags = 0)
|
||||
{
|
||||
$files = glob($pattern, $flags);
|
||||
foreach (glob(dirname($pattern) . '/*', GLOB_ONLYDIR | GLOB_NOSORT) as $dir) {
|
||||
$files = array_merge($files, $this::rglob($dir . '/' . basename($pattern), $flags));
|
||||
foreach (glob(dirname($pattern).'/*', GLOB_ONLYDIR | GLOB_NOSORT) as $dir) {
|
||||
$files = array_merge($files, $this::rglob($dir.'/'.basename($pattern), $flags));
|
||||
}
|
||||
|
||||
return $files;
|
||||
}
|
||||
|
||||
|
@ -53,16 +54,15 @@ class InvoiceController extends Controller
|
|||
try {
|
||||
$query = Invoice::where('payment_id', '=', $id)->firstOrFail();
|
||||
} catch (Throwable $e) {
|
||||
return redirect()->back()->with("error", __("Error!"));
|
||||
return redirect()->back()->with('error', __('Error!'));
|
||||
}
|
||||
|
||||
$invoice_path = storage_path('app/invoice/' . $query->invoice_user . '/' . $query->created_at->format("Y") . '/' . $query->invoice_name . '.pdf');
|
||||
$invoice_path = storage_path('app/invoice/'.$query->invoice_user.'/'.$query->created_at->format('Y').'/'.$query->invoice_name.'.pdf');
|
||||
|
||||
if (!file_exists($invoice_path)) {
|
||||
return redirect()->back()->with("error", __("Invoice does not exist on filesystem!"));
|
||||
if (! file_exists($invoice_path)) {
|
||||
return redirect()->back()->with('error', __('Invoice does not exist on filesystem!'));
|
||||
}
|
||||
|
||||
|
||||
return response()->download($invoice_path);
|
||||
}
|
||||
}
|
||||
|
|
42
app/Http/Controllers/Admin/LegalController.php
Normal file
42
app/Http/Controllers/Admin/LegalController.php
Normal file
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Qirolab\Theme\Theme;
|
||||
|
||||
|
||||
class LegalController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$tos = File::get(Theme::path($path = 'views', "default") . '/information/tos-content.blade.php');
|
||||
$privacy = File::get(Theme::path($path = 'views', "default") . '/information/privacy-content.blade.php');
|
||||
$imprint = File::get(Theme::path($path = 'views', "default") . '/information/imprint-content.blade.php');
|
||||
|
||||
return view('admin.legal.index')->with([
|
||||
"tos" => $tos,
|
||||
"privacy" => $privacy,
|
||||
"imprint" => $imprint,
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(Request $request){
|
||||
$tos = $request->tos;
|
||||
$privacy = $request->privacy;
|
||||
$imprint = $request->imprint;
|
||||
|
||||
File::put(Theme::path($path = 'views', "default") . '/information/tos-content.blade.php', $tos);
|
||||
File::put(Theme::path($path = 'views', "default") . '/information/privacy-content.blade.php', $privacy);
|
||||
File::put(Theme::path($path = 'views', "default") . '/information/imprint-content.blade.php', $imprint);
|
||||
|
||||
return back()->with("success",__("Legal pages updated"));
|
||||
}
|
||||
}
|
|
@ -2,18 +2,17 @@
|
|||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Classes\Pterodactyl;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Egg;
|
||||
use App\Models\Location;
|
||||
use App\Models\Nest;
|
||||
use App\Models\Node;
|
||||
use App\Models\Payment;
|
||||
use App\Models\Server;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use App\Classes\Pterodactyl;
|
||||
use App\Models\Product;
|
||||
use App\Models\Server;
|
||||
use App\Models\Ticket;
|
||||
use App\Models\User;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class OverViewController extends Controller
|
||||
|
@ -26,7 +25,7 @@ class OverViewController extends Controller
|
|||
$counters = collect();
|
||||
//Set basic variables in the collection
|
||||
$counters->put('users', User::query()->count());
|
||||
$counters->put('credits', number_format(User::query()->where("role","!=","admin")->sum('credits'), 2, '.', ''));
|
||||
$counters->put('credits', number_format(User::query()->where('role', '!=', 'admin')->sum('credits'), 2, '.', ''));
|
||||
$counters->put('payments', Payment::query()->count());
|
||||
$counters->put('eggs', Egg::query()->count());
|
||||
$counters->put('nests', Nest::query()->count());
|
||||
|
@ -45,55 +44,109 @@ class OverViewController extends Controller
|
|||
$counters->put('payments', collect());
|
||||
//Get and save payments from last 2 months for later filtering and looping
|
||||
$payments = Payment::query()->where('created_at', '>=', Carbon::today()->startOfMonth()->subMonth())->where('status', 'paid')->get();
|
||||
//Prepare collections and set a few variables
|
||||
//Prepare collections
|
||||
$counters['payments']->put('thisMonth', collect());
|
||||
$counters['payments']->put('lastMonth', collect());
|
||||
$counters['payments']['thisMonth']->timeStart = Carbon::today()->startOfMonth()->toDateString();
|
||||
$counters['payments']['thisMonth']->timeEnd = Carbon::today()->toDateString();
|
||||
$counters['payments']['lastMonth']->timeStart = Carbon::today()->startOfMonth()->subMonth()->toDateString();
|
||||
$counters['payments']['lastMonth']->timeEnd = Carbon::today()->endOfMonth()->subMonth()->toDateString();
|
||||
|
||||
|
||||
|
||||
//Prepare subCollection 'taxPayments'
|
||||
$counters->put('taxPayments', collect());
|
||||
//Get and save taxPayments from last 2 years for later filtering and looping
|
||||
$taxPayments = Payment::query()->where('created_at', '>=', Carbon::today()->startOfYear()->subYear())->where('status', 'paid')->get();
|
||||
//Prepare collections
|
||||
$counters['taxPayments']->put('thisYear', collect());
|
||||
$counters['taxPayments']->put('lastYear', collect());
|
||||
|
||||
//Fill out variables for each currency separately
|
||||
foreach($payments->where('created_at', '>=', Carbon::today()->startOfMonth()) as $payment){
|
||||
foreach ($payments->where('created_at', '>=', Carbon::today()->startOfMonth()) as $payment) {
|
||||
$paymentCurrency = $payment->currency_code;
|
||||
if(!isset($counters['payments']['thisMonth'][$paymentCurrency])){
|
||||
if (! isset($counters['payments']['thisMonth'][$paymentCurrency])) {
|
||||
$counters['payments']['thisMonth']->put($paymentCurrency, collect());
|
||||
$counters['payments']['thisMonth'][$paymentCurrency]->total = 0;
|
||||
$counters['payments']['thisMonth'][$paymentCurrency]->count = 0;
|
||||
}
|
||||
$counters['payments']['thisMonth'][$paymentCurrency]->total += $payment->total_price;
|
||||
$counters['payments']['thisMonth'][$paymentCurrency]->count ++;
|
||||
$counters['payments']['thisMonth'][$paymentCurrency]->count++;
|
||||
}
|
||||
foreach($payments->where('created_at', '<', Carbon::today()->startOfMonth()) as $payment){
|
||||
foreach ($payments->where('created_at', '<', Carbon::today()->startOfMonth()) as $payment) {
|
||||
$paymentCurrency = $payment->currency_code;
|
||||
if(!isset($counters['payments']['lastMonth'][$paymentCurrency])){
|
||||
if (! isset($counters['payments']['lastMonth'][$paymentCurrency])) {
|
||||
$counters['payments']['lastMonth']->put($paymentCurrency, collect());
|
||||
$counters['payments']['lastMonth'][$paymentCurrency]->total = 0;
|
||||
$counters['payments']['lastMonth'][$paymentCurrency]->count = 0;
|
||||
}
|
||||
$counters['payments']['lastMonth'][$paymentCurrency]->total += $payment->total_price;
|
||||
$counters['payments']['lastMonth'][$paymentCurrency]->count ++;
|
||||
$counters['payments']['lastMonth'][$paymentCurrency]->count++;
|
||||
}
|
||||
|
||||
//sort currencies alphabetically and set some additional variables
|
||||
$counters['payments']['thisMonth'] = $counters['payments']['thisMonth']->sortKeys();
|
||||
$counters['payments']['thisMonth']->timeStart = Carbon::today()->startOfMonth()->toDateString();
|
||||
$counters['payments']['thisMonth']->timeEnd = Carbon::today()->toDateString();
|
||||
$counters['payments']['lastMonth'] = $counters['payments']['lastMonth']->sortKeys();
|
||||
$counters['payments']['lastMonth']->timeStart = Carbon::today()->startOfMonth()->subMonth()->toDateString();
|
||||
$counters['payments']['lastMonth']->timeEnd = Carbon::today()->endOfMonth()->subMonth()->toDateString();
|
||||
$counters['payments']->total = Payment::query()->count();
|
||||
|
||||
|
||||
foreach($taxPayments->where('created_at', '>=', Carbon::today()->startOfYear()) as $taxPayment){
|
||||
$paymentCurrency = $taxPayment->currency_code;
|
||||
if(!isset($counters['taxPayments']['thisYear'][$paymentCurrency])){
|
||||
|
||||
$counters['taxPayments']['thisYear']->put($paymentCurrency, collect());
|
||||
$counters['taxPayments']['thisYear'][$paymentCurrency]->total = 0;
|
||||
$counters['taxPayments']['thisYear'][$paymentCurrency]->count = 0;
|
||||
$counters['taxPayments']['thisYear'][$paymentCurrency]->price = 0;
|
||||
$counters['taxPayments']['thisYear'][$paymentCurrency]->taxes = 0;
|
||||
}
|
||||
$counters['taxPayments']['thisYear'][$paymentCurrency]->total += $taxPayment->total_price;
|
||||
$counters['taxPayments']['thisYear'][$paymentCurrency]->count++;
|
||||
$counters['taxPayments']['thisYear'][$paymentCurrency]->price += $taxPayment->price;
|
||||
$counters['taxPayments']['thisYear'][$paymentCurrency]->taxes += $taxPayment->tax_value;
|
||||
}
|
||||
|
||||
foreach($taxPayments->where('created_at', '>=', Carbon::today()->startOfYear()->subYear())->where('created_at', '<', Carbon::today()->startOfYear()) as $taxPayment){
|
||||
$paymentCurrency = $taxPayment->currency_code;
|
||||
if(!isset($counters['taxPayments']['lastYear'][$paymentCurrency])){
|
||||
|
||||
$counters['taxPayments']['lastYear']->put($paymentCurrency, collect());
|
||||
$counters['taxPayments']['lastYear'][$paymentCurrency]->total = 0;
|
||||
$counters['taxPayments']['lastYear'][$paymentCurrency]->count = 0;
|
||||
$counters['taxPayments']['lastYear'][$paymentCurrency]->price = 0;
|
||||
$counters['taxPayments']['lastYear'][$paymentCurrency]->taxes = 0;
|
||||
}
|
||||
$counters['taxPayments']['lastYear'][$paymentCurrency]->total += $taxPayment->total_price;
|
||||
$counters['taxPayments']['lastYear'][$paymentCurrency]->count++;
|
||||
$counters['taxPayments']['lastYear'][$paymentCurrency]->price += $taxPayment->price;
|
||||
$counters['taxPayments']['lastYear'][$paymentCurrency]->taxes += $taxPayment->tax_value;
|
||||
}
|
||||
|
||||
//sort currencies alphabetically and set some additional variables
|
||||
$counters['taxPayments']['thisYear'] = $counters['taxPayments']['thisYear']->sortKeys();
|
||||
$counters['taxPayments']['thisYear']->timeStart = Carbon::today()->startOfYear()->toDateString();
|
||||
$counters['taxPayments']['thisYear']->timeEnd = Carbon::today()->toDateString();
|
||||
$counters['taxPayments']['lastYear'] = $counters['taxPayments']['lastYear']->sortKeys();
|
||||
$counters['taxPayments']['lastYear']->timeStart = Carbon::today()->startOfYear()->subYear()->toDateString();
|
||||
$counters['taxPayments']['lastYear']->timeEnd = Carbon::today()->endOfYear()->subYear()->toDateString();
|
||||
|
||||
$lastEgg = Egg::query()->latest('updated_at')->first();
|
||||
$syncLastUpdate = $lastEgg ? $lastEgg->updated_at->isoFormat('LLL') : __('unknown');
|
||||
|
||||
|
||||
|
||||
//Get node information and prepare collection
|
||||
$pteroNodeIds = [];
|
||||
foreach(Pterodactyl::getNodes() as $pteroNode){
|
||||
foreach (Pterodactyl::getNodes() as $pteroNode) {
|
||||
array_push($pteroNodeIds, $pteroNode['attributes']['id']);
|
||||
}
|
||||
$nodes = collect();
|
||||
foreach($DBnodes = Node::query()->get() as $DBnode){ //gets all node information and prepares the structure
|
||||
foreach ($DBnodes = Node::query()->get() as $DBnode) { //gets all node information and prepares the structure
|
||||
$nodeId = $DBnode['id'];
|
||||
if(!in_array($nodeId, $pteroNodeIds)) continue; //Check if node exists on pterodactyl too, if not, skip
|
||||
if (! in_array($nodeId, $pteroNodeIds)) {
|
||||
continue;
|
||||
} //Check if node exists on pterodactyl too, if not, skip
|
||||
$nodes->put($nodeId, collect());
|
||||
$nodes[$nodeId]->name = $DBnode['name'];
|
||||
$pteroNode = Pterodactyl::getNode($nodeId);
|
||||
$nodes[$nodeId]->usagePercent = round(max($pteroNode['allocated_resources']['memory']/($pteroNode['memory']*($pteroNode['memory_overallocate']+100)/100), $pteroNode['allocated_resources']['disk']/($pteroNode['disk']*($pteroNode['disk_overallocate']+100)/100))*100, 2);
|
||||
$nodes[$nodeId]->usagePercent = round(max($pteroNode['allocated_resources']['memory'] / ($pteroNode['memory'] * ($pteroNode['memory_overallocate'] + 100) / 100), $pteroNode['allocated_resources']['disk'] / ($pteroNode['disk'] * ($pteroNode['disk_overallocate'] + 100) / 100)) * 100, 2);
|
||||
$counters['totalUsagePercent'] += $nodes[$nodeId]->usagePercent;
|
||||
|
||||
$nodes[$nodeId]->totalServers = 0;
|
||||
|
@ -101,66 +154,61 @@ class OverViewController extends Controller
|
|||
$nodes[$nodeId]->totalEarnings = 0;
|
||||
$nodes[$nodeId]->activeEarnings = 0;
|
||||
}
|
||||
$counters['totalUsagePercent'] = ($DBnodes->count())?round($counters['totalUsagePercent']/$DBnodes->count(), 2):0;
|
||||
$counters['totalUsagePercent'] = ($DBnodes->count()) ? round($counters['totalUsagePercent'] / $DBnodes->count(), 2) : 0;
|
||||
|
||||
foreach(Pterodactyl::getServers() as $server){ //gets all servers from Pterodactyl and calculates total of credit usage for each node separately + total
|
||||
foreach (Pterodactyl::getServers() as $server) { //gets all servers from Pterodactyl and calculates total of credit usage for each node separately + total
|
||||
$nodeId = $server['attributes']['node'];
|
||||
|
||||
if($CPServer = Server::query()->where('pterodactyl_id', $server['attributes']['id'])->first()){
|
||||
|
||||
if ($CPServer = Server::query()->where('pterodactyl_id', $server['attributes']['id'])->first()) {
|
||||
$price = Product::query()->where('id', $CPServer->product_id)->first()->price;
|
||||
if (!$CPServer->suspended){
|
||||
if (! $CPServer->suspended) {
|
||||
$counters['earnings']->active += $price;
|
||||
$counters['servers']->active ++;
|
||||
$counters['servers']->active++;
|
||||
$nodes[$nodeId]->activeEarnings += $price;
|
||||
$nodes[$nodeId]->activeServers ++;
|
||||
$nodes[$nodeId]->activeServers++;
|
||||
}
|
||||
$counters['earnings']->total += $price;
|
||||
$counters['servers']->total ++;
|
||||
$counters['servers']->total++;
|
||||
$nodes[$nodeId]->totalEarnings += $price;
|
||||
$nodes[$nodeId]->totalServers ++;
|
||||
$nodes[$nodeId]->totalServers++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Get latest tickets
|
||||
$tickets = Cache::remember('tickets', self::TTL, function(){
|
||||
$output = collect();
|
||||
foreach(Ticket::query()->latest()->take(3)->get() as $ticket){
|
||||
$output->put($ticket->ticket_id, collect());
|
||||
$output[$ticket->ticket_id]->title = $ticket->title;
|
||||
$user = User::query()->where('id', $ticket->user_id)->first();
|
||||
$output[$ticket->ticket_id]->user_id = $user->id;
|
||||
$output[$ticket->ticket_id]->user = $user->name;
|
||||
$output[$ticket->ticket_id]->status = $ticket->status;
|
||||
$output[$ticket->ticket_id]->last_updated = $ticket->updated_at->diffForHumans();
|
||||
switch ($ticket->status) {
|
||||
case 'Open':
|
||||
$output[$ticket->ticket_id]->statusBadgeColor = 'badge-success';
|
||||
break;
|
||||
case 'Closed':
|
||||
$output[$ticket->ticket_id]->statusBadgeColor = 'badge-danger';
|
||||
break;
|
||||
case 'Answered':
|
||||
$output[$ticket->ticket_id]->statusBadgeColor = 'badge-info';
|
||||
break;
|
||||
default:
|
||||
$output[$ticket->ticket_id]->statusBadgeColor = 'badge-warning';
|
||||
break;
|
||||
}
|
||||
$tickets = collect();
|
||||
foreach (Ticket::query()->latest()->take(5)->get() as $ticket) {
|
||||
$tickets->put($ticket->ticket_id, collect());
|
||||
$tickets[$ticket->ticket_id]->title = $ticket->title;
|
||||
$user = User::query()->where('id', $ticket->user_id)->first();
|
||||
$tickets[$ticket->ticket_id]->user_id = $user->id;
|
||||
$tickets[$ticket->ticket_id]->user = $user->name;
|
||||
$tickets[$ticket->ticket_id]->status = $ticket->status;
|
||||
$tickets[$ticket->ticket_id]->last_updated = $ticket->updated_at->diffForHumans();
|
||||
switch ($ticket->status) {
|
||||
case 'Open':
|
||||
$tickets[$ticket->ticket_id]->statusBadgeColor = 'badge-success';
|
||||
break;
|
||||
case 'Closed':
|
||||
$tickets[$ticket->ticket_id]->statusBadgeColor = 'badge-danger';
|
||||
break;
|
||||
case 'Answered':
|
||||
$tickets[$ticket->ticket_id]->statusBadgeColor = 'badge-info';
|
||||
break;
|
||||
default:
|
||||
$tickets[$ticket->ticket_id]->statusBadgeColor = 'badge-warning';
|
||||
break;
|
||||
}
|
||||
return $output;
|
||||
});
|
||||
}
|
||||
|
||||
return view('admin.overview.index', [
|
||||
'counters' => $counters,
|
||||
'nodes' => $nodes,
|
||||
'counters' => $counters,
|
||||
'nodes' => $nodes,
|
||||
'syncLastUpdate' => $syncLastUpdate,
|
||||
'deletedNodesPresent'=> ($DBnodes->count() != count($pteroNodeIds))?true:false,
|
||||
'perPageLimit' => ($counters['servers']->total != Server::query()->count())?true:false,
|
||||
'tickets' => $tickets
|
||||
'deletedNodesPresent' => ($DBnodes->count() != count($pteroNodeIds)) ? true : false,
|
||||
'perPageLimit' => ($counters['servers']->total != Server::query()->count()) ? true : false,
|
||||
'tickets' => $tickets,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Sync locations,nodes,nests,eggs with the linked pterodactyl panel
|
||||
|
|
137
app/Http/Controllers/Admin/PartnerController.php
Normal file
137
app/Http/Controllers/Admin/PartnerController.php
Normal file
|
@ -0,0 +1,137 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\PartnerDiscount;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class PartnerController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
return view('admin.partners.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return Application|Factory|View
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
return view('admin.partners.create', [
|
||||
'partners' => PartnerDiscount::get(),
|
||||
'users' => User::orderBy('name')->get(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'user_id' => 'required|integer|min:0',
|
||||
'partner_discount' => 'required|integer|max:100|min:0',
|
||||
'registered_user_discount' => 'required|integer|max:100|min:0',
|
||||
]);
|
||||
|
||||
if(PartnerDiscount::where("user_id",$request->user_id)->exists()){
|
||||
return redirect()->route('admin.partners.index')->with('error', __('Partner already exists'));
|
||||
}
|
||||
|
||||
PartnerDiscount::create($request->all());
|
||||
|
||||
return redirect()->route('admin.partners.index')->with('success', __('partner has been created!'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param Partner $partner
|
||||
* @return Application|Factory|View
|
||||
*/
|
||||
public function edit(PartnerDiscount $partner)
|
||||
{
|
||||
return view('admin.partners.edit', [
|
||||
'partners' => PartnerDiscount::get(),
|
||||
'partner' => $partner,
|
||||
'users' => User::orderBy('name')->get(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Partner $partner
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function update(Request $request, PartnerDiscount $partner)
|
||||
{
|
||||
//dd($request);
|
||||
$request->validate([
|
||||
'user_id' => 'required|integer|min:0',
|
||||
'partner_discount' => 'required|integer|max:100|min:0',
|
||||
'registered_user_discount' => 'required|integer|max:100|min:0',
|
||||
]);
|
||||
|
||||
$partner->update($request->all());
|
||||
|
||||
return redirect()->route('admin.partners.index')->with('success', __('partner has been updated!'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param Partner $partner
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function destroy(PartnerDiscount $partner)
|
||||
{
|
||||
$partner->delete();
|
||||
|
||||
return redirect()->back()->with('success', __('partner has been removed!'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function dataTable()
|
||||
{
|
||||
$query = PartnerDiscount::query();
|
||||
|
||||
return datatables($query)
|
||||
->addColumn('actions', function (PartnerDiscount $partner) {
|
||||
return '
|
||||
<a data-content="'.__('Edit').'" data-toggle="popover" data-trigger="hover" data-placement="top" href="'.route('admin.partners.edit', $partner->id).'" class="btn btn-sm btn-info mr-1"><i class="fas fa-pen"></i></a>
|
||||
<form class="d-inline" onsubmit="return submitResult();" method="post" action="'.route('admin.partners.destroy', $partner->id).'">
|
||||
'.csrf_field().'
|
||||
'.method_field('DELETE').'
|
||||
<button data-content="'.__('Delete').'" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm btn-danger mr-1"><i class="fas fa-trash"></i></button>
|
||||
</form>
|
||||
';
|
||||
})
|
||||
->addColumn('user', function (PartnerDiscount $partner) {
|
||||
return ($user = User::where('id', $partner->user_id)->first()) ? '<a href="'.route('admin.users.show', $partner->user_id).'">'.$user->name.'</a>' : __('Unknown user');
|
||||
})
|
||||
->editColumn('created_at', function (PartnerDiscount $partner) {
|
||||
return $partner->created_at ? $partner->created_at->diffForHumans() : '';
|
||||
})
|
||||
->editColumn('partner_discount', function (PartnerDiscount $partner) {
|
||||
return $partner->partner_discount ? $partner->partner_discount.'%' : '0%';
|
||||
})
|
||||
->editColumn('registered_user_discount', function (PartnerDiscount $partner) {
|
||||
return $partner->registered_user_discount ? $partner->registered_user_discount.'%' : '0%';
|
||||
})
|
||||
->editColumn('referral_system_commission', function (PartnerDiscount $partner) {
|
||||
return $partner->referral_system_commission >= 0 ? $partner->referral_system_commission.'%' : __('Default').' ('.config('SETTINGS::REFERRAL:PERCENTAGE').'%)';
|
||||
})
|
||||
->rawColumns(['user', 'actions'])
|
||||
->make();
|
||||
}
|
||||
}
|
|
@ -2,15 +2,13 @@
|
|||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Events\PaymentEvent;
|
||||
use App\Events\UserUpdateCreditsEvent;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\InvoiceSettings;
|
||||
use App\Models\PartnerDiscount;
|
||||
use App\Models\Payment;
|
||||
use App\Models\ShopProduct;
|
||||
use App\Models\Settings;
|
||||
use App\Models\User;
|
||||
use App\Notifications\InvoiceNotification;
|
||||
use App\Notifications\ConfirmPaymentNotification;
|
||||
use App\Models\ShopProduct;
|
||||
use Exception;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
|
@ -19,633 +17,125 @@ use Illuminate\Http\JsonResponse;
|
|||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use LaravelDaily\Invoices\Classes\Buyer;
|
||||
use LaravelDaily\Invoices\Classes\InvoiceItem;
|
||||
use LaravelDaily\Invoices\Classes\Party;
|
||||
use LaravelDaily\Invoices\Invoice;
|
||||
use PayPalCheckoutSdk\Core\PayPalHttpClient;
|
||||
use PayPalCheckoutSdk\Core\ProductionEnvironment;
|
||||
use PayPalCheckoutSdk\Core\SandboxEnvironment;
|
||||
use PayPalCheckoutSdk\Orders\OrdersCaptureRequest;
|
||||
use PayPalCheckoutSdk\Orders\OrdersCreateRequest;
|
||||
use PayPalHttp\HttpException;
|
||||
use Stripe\Stripe;
|
||||
use Symfony\Component\Intl\Currencies;
|
||||
use App\Helpers\ExtensionHelper;
|
||||
|
||||
|
||||
class PaymentController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @return Application|Factory|View
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('admin.payments.index')->with([
|
||||
'payments' => Payment::paginate(15)
|
||||
'payments' => Payment::paginate(15),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param ShopProduct $shopProduct
|
||||
* @param Request $request
|
||||
* @param ShopProduct $shopProduct
|
||||
* @return Application|Factory|View
|
||||
*/
|
||||
public function checkOut(Request $request, ShopProduct $shopProduct)
|
||||
public function checkOut(ShopProduct $shopProduct)
|
||||
{
|
||||
$discount = PartnerDiscount::getDiscount();
|
||||
$price = $shopProduct->price - ($shopProduct->price * $discount / 100);
|
||||
|
||||
$paymentGateways = [];
|
||||
if ($price > 0) {
|
||||
$extensions = ExtensionHelper::getAllExtensionsByNamespace('PaymentGateways');
|
||||
|
||||
// build a paymentgateways array that contains the routes for the payment gateways and the image path for the payment gateway which lays in public/images/Extensions/PaymentGateways with the extensionname in lowercase
|
||||
foreach ($extensions as $extension) {
|
||||
$extensionName = basename($extension);
|
||||
if (!ExtensionHelper::getExtensionConfig($extensionName, 'enabled')) continue; // skip if not enabled
|
||||
|
||||
$payment = new \stdClass();
|
||||
$payment->name = ExtensionHelper::getExtensionConfig($extensionName, 'name');
|
||||
$payment->image = asset('images/Extensions/PaymentGateways/' . strtolower($extensionName) . '_logo.png');
|
||||
$paymentGateways[] = $payment;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return view('store.checkout')->with([
|
||||
'product' => $shopProduct,
|
||||
'taxvalue' => $shopProduct->getTaxValue(),
|
||||
'taxpercent' => $shopProduct->getTaxPercent(),
|
||||
'total' => $shopProduct->getTotalPrice()
|
||||
'product' => $shopProduct,
|
||||
'discountpercent' => $discount,
|
||||
'discountvalue' => $discount * $shopProduct->price / 100,
|
||||
'discountedprice' => $shopProduct->getPriceAfterDiscount(),
|
||||
'taxvalue' => $shopProduct->getTaxValue(),
|
||||
'taxpercent' => $shopProduct->getTaxPercent(),
|
||||
'total' => $shopProduct->getTotalPrice(),
|
||||
'paymentGateways' => $paymentGateways,
|
||||
'productIsFree' => $price <= 0,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param ShopProduct $shopProduct
|
||||
* @param Request $request
|
||||
* @param ShopProduct $shopProduct
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function PaypalPay(Request $request, ShopProduct $shopProduct)
|
||||
public function handleFreeProduct(ShopProduct $shopProduct)
|
||||
{
|
||||
$request = new OrdersCreateRequest();
|
||||
$request->prefer('return=representation');
|
||||
$request->body = [
|
||||
"intent" => "CAPTURE",
|
||||
"purchase_units" => [
|
||||
[
|
||||
"reference_id" => uniqid(),
|
||||
"description" => $shopProduct->description,
|
||||
"amount" => [
|
||||
"value" => $shopProduct->getTotalPrice(),
|
||||
'currency_code' => strtoupper($shopProduct->currency_code),
|
||||
'breakdown' => [
|
||||
'item_total' =>
|
||||
[
|
||||
'currency_code' => strtoupper($shopProduct->currency_code),
|
||||
'value' => $shopProduct->price,
|
||||
],
|
||||
'tax_total' =>
|
||||
[
|
||||
'currency_code' => strtoupper($shopProduct->currency_code),
|
||||
'value' => $shopProduct->getTaxValue(),
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
"application_context" => [
|
||||
"cancel_url" => route('payment.Cancel'),
|
||||
"return_url" => route('payment.PaypalSuccess', ['product' => $shopProduct->id]),
|
||||
'brand_name' => config('app.name', 'Laravel'),
|
||||
'shipping_preference' => 'NO_SHIPPING'
|
||||
]
|
||||
|
||||
|
||||
];
|
||||
|
||||
|
||||
try {
|
||||
// Call API with your client and get a response for your call
|
||||
$response = $this->getPayPalClient()->execute($request);
|
||||
return redirect()->away($response->result->links[1]->href);
|
||||
|
||||
// If call returns body in response, you can get the deserialized version from the result attribute of the response
|
||||
} catch (HttpException $ex) {
|
||||
echo $ex->statusCode;
|
||||
dd(json_decode($ex->getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PayPalHttpClient
|
||||
*/
|
||||
protected function getPayPalClient()
|
||||
{
|
||||
$environment = env('APP_ENV') == 'local'
|
||||
? new SandboxEnvironment($this->getPaypalClientId(), $this->getPaypalClientSecret())
|
||||
: new ProductionEnvironment($this->getPaypalClientId(), $this->getPaypalClientSecret());
|
||||
|
||||
return new PayPalHttpClient($environment);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected function getPaypalClientId()
|
||||
{
|
||||
return env('APP_ENV') == 'local' ? config("SETTINGS::PAYMENTS:PAYPAL:SANDBOX_CLIENT_ID") : config("SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected function getPaypalClientSecret()
|
||||
{
|
||||
return env('APP_ENV') == 'local' ? config("SETTINGS::PAYMENTS:PAYPAL:SANDBOX_SECRET") : config("SETTINGS::PAYMENTS:PAYPAL:SECRET");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $laravelRequest
|
||||
*/
|
||||
public function PaypalSuccess(Request $laravelRequest)
|
||||
{
|
||||
/** @var ShopProduct $shopProduct */
|
||||
$shopProduct = ShopProduct::findOrFail($laravelRequest->input('product'));
|
||||
|
||||
/** @var User $user */
|
||||
$user = Auth::user();
|
||||
|
||||
$request = new OrdersCaptureRequest($laravelRequest->input('token'));
|
||||
$request->prefer('return=representation');
|
||||
try {
|
||||
// Call API with your client and get a response for your call
|
||||
$response = $this->getPayPalClient()->execute($request);
|
||||
if ($response->statusCode == 201 || $response->statusCode == 200) {
|
||||
//create a payment
|
||||
$payment = Payment::create([
|
||||
'user_id' => $user->id,
|
||||
'payment_id' => uniqid(),
|
||||
'payment_method' => 'free',
|
||||
'type' => $shopProduct->type,
|
||||
'status' => 'paid',
|
||||
'amount' => $shopProduct->quantity,
|
||||
'price' => $shopProduct->price - ($shopProduct->price * PartnerDiscount::getDiscount() / 100),
|
||||
'tax_value' => $shopProduct->getTaxValue(),
|
||||
'tax_percent' => $shopProduct->getTaxPercent(),
|
||||
'total_price' => $shopProduct->getTotalPrice(),
|
||||
'currency_code' => $shopProduct->currency_code,
|
||||
'shop_item_product_id' => $shopProduct->id,
|
||||
]);
|
||||
|
||||
//update server limit
|
||||
if (config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE') !== 0) {
|
||||
if ($user->server_limit < config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')) {
|
||||
$user->update(['server_limit' => config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')]);
|
||||
}
|
||||
}
|
||||
event(new UserUpdateCreditsEvent($user));
|
||||
event(new PaymentEvent($user, $payment, $shopProduct));
|
||||
|
||||
//update User with bought item
|
||||
if ($shopProduct->type=="Credits") {
|
||||
$user->increment('credits', $shopProduct->quantity);
|
||||
}elseif ($shopProduct->type=="Server slots"){
|
||||
$user->increment('server_limit', $shopProduct->quantity);
|
||||
}
|
||||
//not sending an invoice
|
||||
|
||||
|
||||
//update role give Referral-reward
|
||||
if ($user->role == 'member') {
|
||||
$user->update(['role' => 'client']);
|
||||
|
||||
if((config("SETTINGS::REFERRAL:MODE") == "commission" || config("SETTINGS::REFERRAL:MODE") == "both") && $shopProduct->type=="Credits"){
|
||||
if($ref_user = DB::table("user_referrals")->where('registered_user_id', '=', $user->id)->first()){
|
||||
$ref_user = User::findOrFail($ref_user->referral_id);
|
||||
$increment = number_format($shopProduct->quantity/100*config("SETTINGS::REFERRAL:PERCENTAGE"),0,"","");
|
||||
$ref_user->increment('credits', $increment);
|
||||
|
||||
//LOGS REFERRALS IN THE ACTIVITY LOG
|
||||
activity()
|
||||
->performedOn($user)
|
||||
->causedBy($ref_user)
|
||||
->log('gained '. $increment.' '.config("SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME").' for commission-referral of '.$user->name.' (ID:'.$user->id.')');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//store payment
|
||||
$payment = Payment::create([
|
||||
'user_id' => $user->id,
|
||||
'payment_id' => $response->result->id,
|
||||
'payment_method' => 'paypal',
|
||||
'type' => $shopProduct->type,
|
||||
'status' => 'paid',
|
||||
'amount' => $shopProduct->quantity,
|
||||
'price' => $shopProduct->price,
|
||||
'tax_value' => $shopProduct->getTaxValue(),
|
||||
'tax_percent' => $shopProduct->getTaxPercent(),
|
||||
'total_price' => $shopProduct->getTotalPrice(),
|
||||
'currency_code' => $shopProduct->currency_code,
|
||||
'shop_item_product_id' => $shopProduct->id,
|
||||
]);
|
||||
|
||||
|
||||
event(new UserUpdateCreditsEvent($user));
|
||||
|
||||
//only create invoice if SETTINGS::INVOICE:ENABLED is true
|
||||
if (config('SETTINGS::INVOICE:ENABLED') == 'true') {
|
||||
$this->createInvoice($user, $payment, 'paid', $shopProduct->currency_code);
|
||||
}
|
||||
|
||||
|
||||
//redirect back to home
|
||||
return redirect()->route('home')->with('success', __('Your credit balance has been increased!'));
|
||||
}
|
||||
|
||||
|
||||
// If call returns body in response, you can get the deserialized version from the result attribute of the response
|
||||
if (env('APP_ENV') == 'local') {
|
||||
dd($response);
|
||||
} else {
|
||||
abort(500);
|
||||
}
|
||||
} catch (HttpException $ex) {
|
||||
if (env('APP_ENV') == 'local') {
|
||||
echo $ex->statusCode;
|
||||
dd($ex->getMessage());
|
||||
} else {
|
||||
abort(422);
|
||||
}
|
||||
}
|
||||
//redirect back to home
|
||||
return redirect()->route('home')->with('success', __('Your credit balance has been increased!'));
|
||||
}
|
||||
|
||||
public function pay(Request $request)
|
||||
{
|
||||
$product = ShopProduct::find($request->product_id);
|
||||
$paymentGateway = $request->payment_method;
|
||||
|
||||
// on free products, we don't need to use a payment gateway
|
||||
$realPrice = $product->price - ($product->price * PartnerDiscount::getDiscount() / 100);
|
||||
if ($realPrice <= 0) {
|
||||
return $this->handleFreeProduct($product);
|
||||
}
|
||||
|
||||
return redirect()->route('payment.' . $paymentGateway . 'Pay', ['shopProduct' => $product->id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Request $request
|
||||
*/
|
||||
public function Cancel(Request $request)
|
||||
{
|
||||
return redirect()->route('store.index')->with('success', 'Payment was Canceled');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param ShopProduct $shopProduct
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function StripePay(Request $request, ShopProduct $shopProduct)
|
||||
{
|
||||
$stripeClient = $this->getStripeClient();
|
||||
|
||||
|
||||
$request = $stripeClient->checkout->sessions->create([
|
||||
'line_items' => [
|
||||
[
|
||||
'price_data' => [
|
||||
'currency' => $shopProduct->currency_code,
|
||||
'product_data' => [
|
||||
'name' => $shopProduct->display,
|
||||
'description' => $shopProduct->description,
|
||||
],
|
||||
'unit_amount_decimal' => round($shopProduct->price * 100, 2),
|
||||
],
|
||||
'quantity' => 1,
|
||||
],
|
||||
[
|
||||
'price_data' => [
|
||||
'currency' => $shopProduct->currency_code,
|
||||
'product_data' => [
|
||||
'name' => 'Product Tax',
|
||||
'description' => $shopProduct->getTaxPercent() . "%",
|
||||
],
|
||||
'unit_amount_decimal' => round($shopProduct->getTaxValue(), 2) * 100,
|
||||
],
|
||||
'quantity' => 1,
|
||||
]
|
||||
],
|
||||
|
||||
'mode' => 'payment',
|
||||
"payment_method_types" => str_getcsv(config("SETTINGS::PAYMENTS:STRIPE:METHODS")),
|
||||
'success_url' => route('payment.StripeSuccess', ['product' => $shopProduct->id]) . '&session_id={CHECKOUT_SESSION_ID}',
|
||||
'cancel_url' => route('payment.Cancel'),
|
||||
]);
|
||||
|
||||
|
||||
|
||||
return redirect($request->url, 303);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
*/
|
||||
public function StripeSuccess(Request $request)
|
||||
{
|
||||
/** @var ShopProduct $shopProduct */
|
||||
$shopProduct = ShopProduct::findOrFail($request->input('product'));
|
||||
|
||||
/** @var User $user */
|
||||
$user = Auth::user();
|
||||
|
||||
$stripeClient = $this->getStripeClient();
|
||||
|
||||
try {
|
||||
//get stripe data
|
||||
$paymentSession = $stripeClient->checkout->sessions->retrieve($request->input('session_id'));
|
||||
$paymentIntent = $stripeClient->paymentIntents->retrieve($paymentSession->payment_intent);
|
||||
|
||||
//get DB entry of this payment ID if existing
|
||||
$paymentDbEntry = Payment::where('payment_id', $paymentSession->payment_intent)->count();
|
||||
|
||||
// check if payment is 100% completed and payment does not exist in db already
|
||||
if ($paymentSession->status == "complete" && $paymentIntent->status == "succeeded" && $paymentDbEntry == 0) {
|
||||
|
||||
|
||||
|
||||
//update server limit
|
||||
if (config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE') !== 0) {
|
||||
if ($user->server_limit < config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')) {
|
||||
$user->update(['server_limit' => config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')]);
|
||||
}
|
||||
}
|
||||
|
||||
//update User with bought item
|
||||
if ($shopProduct->type=="Credits") {
|
||||
$user->increment('credits', $shopProduct->quantity);
|
||||
}elseif ($shopProduct->type=="Server slots"){
|
||||
$user->increment('server_limit', $shopProduct->quantity);
|
||||
}
|
||||
|
||||
//update role give Referral-reward
|
||||
if ($user->role == 'member') {
|
||||
$user->update(['role' => 'client']);
|
||||
|
||||
if((config("SETTINGS::REFERRAL:MODE") == "commission" || config("SETTINGS::REFERRAL:MODE") == "both") && $shopProduct->type=="Credits"){
|
||||
if($ref_user = DB::table("user_referrals")->where('registered_user_id', '=', $user->id)->first()){
|
||||
$ref_user = User::findOrFail($ref_user->referral_id);
|
||||
$increment = number_format($shopProduct->quantity/100*config("SETTINGS::REFERRAL:PERCENTAGE"),0,"","");
|
||||
$ref_user->increment('credits', $increment);
|
||||
|
||||
//LOGS REFERRALS IN THE ACTIVITY LOG
|
||||
activity()
|
||||
->performedOn($user)
|
||||
->causedBy($ref_user)
|
||||
->log('gained '. $increment.' '.config("SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME").' for commission-referral of '.$user->name.' (ID:'.$user->id.')');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//store paid payment
|
||||
$payment = Payment::create([
|
||||
'user_id' => $user->id,
|
||||
'payment_id' => $paymentSession->payment_intent,
|
||||
'payment_method' => 'stripe',
|
||||
'type' => $shopProduct->type,
|
||||
'status' => 'paid',
|
||||
'amount' => $shopProduct->quantity,
|
||||
'price' => $shopProduct->price,
|
||||
'tax_value' => $shopProduct->getTaxValue(),
|
||||
'total_price' => $shopProduct->getTotalPrice(),
|
||||
'tax_percent' => $shopProduct->getTaxPercent(),
|
||||
'currency_code' => $shopProduct->currency_code,
|
||||
'shop_item_product_id' => $shopProduct->id,
|
||||
]);
|
||||
|
||||
//payment notification
|
||||
$user->notify(new ConfirmPaymentNotification($payment));
|
||||
|
||||
event(new UserUpdateCreditsEvent($user));
|
||||
|
||||
//only create invoice if SETTINGS::INVOICE:ENABLED is true
|
||||
if (config('SETTINGS::INVOICE:ENABLED') == 'true') {
|
||||
$this->createInvoice($user, $payment, 'paid', $shopProduct->currency_code);
|
||||
}
|
||||
|
||||
//redirect back to home
|
||||
return redirect()->route('home')->with('success', __('Your credit balance has been increased!'));
|
||||
} else {
|
||||
if ($paymentIntent->status == "processing") {
|
||||
|
||||
//store processing payment
|
||||
$payment = Payment::create([
|
||||
'user_id' => $user->id,
|
||||
'payment_id' => $paymentSession->payment_intent,
|
||||
'payment_method' => 'stripe',
|
||||
'type' => $shopProduct->type,
|
||||
'status' => 'processing',
|
||||
'amount' => $shopProduct->quantity,
|
||||
'price' => $shopProduct->price,
|
||||
'tax_value' => $shopProduct->getTaxValue(),
|
||||
'total_price' => $shopProduct->getTotalPrice(),
|
||||
'tax_percent' => $shopProduct->getTaxPercent(),
|
||||
'currency_code' => $shopProduct->currency_code,
|
||||
'shop_item_product_id' => $shopProduct->id,
|
||||
]);
|
||||
|
||||
//only create invoice if SETTINGS::INVOICE:ENABLED is true
|
||||
if (config('SETTINGS::INVOICE:ENABLED') == 'true') {
|
||||
$this->createInvoice($user, $payment, 'paid', $shopProduct->currency_code);
|
||||
}
|
||||
|
||||
//redirect back to home
|
||||
return redirect()->route('home')->with('success', __('Your payment is being processed!'));
|
||||
}
|
||||
if ($paymentDbEntry == 0 && $paymentIntent->status != "processing") {
|
||||
$stripeClient->paymentIntents->cancel($paymentIntent->id);
|
||||
|
||||
//redirect back to home
|
||||
return redirect()->route('home')->with('success', __('Your payment has been canceled!'));
|
||||
} else {
|
||||
abort(402);
|
||||
}
|
||||
}
|
||||
} catch (HttpException $ex) {
|
||||
if (env('APP_ENV') == 'local') {
|
||||
echo $ex->statusCode;
|
||||
dd($ex->getMessage());
|
||||
} else {
|
||||
abort(422);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
*/
|
||||
protected function handleStripePaymentSuccessHook($paymentIntent)
|
||||
{
|
||||
try {
|
||||
// Get payment db entry
|
||||
$payment = Payment::where('payment_id', $paymentIntent->id)->first();
|
||||
$user = User::where('id', $payment->user_id)->first();
|
||||
|
||||
if ($paymentIntent->status == 'succeeded' && $payment->status == 'processing') {
|
||||
|
||||
|
||||
//update server limit
|
||||
if (config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE') !== 0) {
|
||||
if ($user->server_limit < config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')) {
|
||||
$user->update(['server_limit' => config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')]);
|
||||
}
|
||||
}
|
||||
//update User with bought item
|
||||
if ($shopProduct->type=="Credits") {
|
||||
$user->increment('credits', $shopProduct->quantity);
|
||||
}elseif ($shopProduct->type=="Server slots"){
|
||||
$user->increment('server_limit', $shopProduct->quantity);
|
||||
}
|
||||
|
||||
//update role give Referral-reward
|
||||
if ($user->role == 'member') {
|
||||
$user->update(['role' => 'client']);
|
||||
|
||||
if((config("SETTINGS::REFERRAL:MODE") == "commission" || config("SETTINGS::REFERRAL:MODE") == "both")&& $shopProduct->type=="Credits"){
|
||||
if($ref_user = DB::table("user_referrals")->where('registered_user_id', '=', $user->id)->first()){
|
||||
$ref_user = User::findOrFail($ref_user->referral_id);
|
||||
$increment = number_format($shopProduct->quantity/100*config("SETTINGS::REFERRAL:PERCENTAGE"),0,"","");
|
||||
$ref_user->increment('credits', $increment);
|
||||
|
||||
//LOGS REFERRALS IN THE ACTIVITY LOG
|
||||
activity()
|
||||
->performedOn($user)
|
||||
->causedBy($ref_user)
|
||||
->log('gained '. $increment.' '.config("SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME").' for commission-referral of '.$user->name.' (ID:'.$user->id.')');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//update payment db entry status
|
||||
$payment->update(['status' => 'paid']);
|
||||
|
||||
//payment notification
|
||||
$user->notify(new ConfirmPaymentNotification($payment));
|
||||
event(new UserUpdateCreditsEvent($user));
|
||||
|
||||
//only create invoice if SETTINGS::INVOICE:ENABLED is true
|
||||
if (config('SETTINGS::INVOICE:ENABLED') == 'true') {
|
||||
$this->createInvoice($user, $payment, 'paid', strtoupper($paymentIntent->currency));
|
||||
}
|
||||
}
|
||||
} catch (HttpException $ex) {
|
||||
abort(422);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
*/
|
||||
public function StripeWebhooks(Request $request)
|
||||
{
|
||||
\Stripe\Stripe::setApiKey($this->getStripeSecret());
|
||||
|
||||
try {
|
||||
$payload = @file_get_contents('php://input');
|
||||
$sig_header = $request->header('Stripe-Signature');
|
||||
$event = null;
|
||||
$event = \Stripe\Webhook::constructEvent(
|
||||
$payload,
|
||||
$sig_header,
|
||||
$this->getStripeEndpointSecret()
|
||||
);
|
||||
} catch (\UnexpectedValueException $e) {
|
||||
// Invalid payload
|
||||
|
||||
abort(400);
|
||||
} catch (\Stripe\Exception\SignatureVerificationException $e) {
|
||||
// Invalid signature
|
||||
|
||||
abort(400);
|
||||
}
|
||||
|
||||
// Handle the event
|
||||
switch ($event->type) {
|
||||
case 'payment_intent.succeeded':
|
||||
$paymentIntent = $event->data->object; // contains a \Stripe\PaymentIntent
|
||||
$this->handleStripePaymentSuccessHook($paymentIntent);
|
||||
break;
|
||||
default:
|
||||
echo 'Received unknown event type ' . $event->type;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Stripe\StripeClient
|
||||
*/
|
||||
protected function getStripeClient()
|
||||
{
|
||||
return new \Stripe\StripeClient($this->getStripeSecret());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected function getStripeSecret()
|
||||
{
|
||||
return env('APP_ENV') == 'local'
|
||||
? config("SETTINGS::PAYMENTS:STRIPE:TEST_SECRET")
|
||||
: config("SETTINGS::PAYMENTS:STRIPE:SECRET");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected function getStripeEndpointSecret()
|
||||
{
|
||||
return env('APP_ENV') == 'local'
|
||||
? config("SETTINGS::PAYMENTS:STRIPE:ENDPOINT_TEST_SECRET")
|
||||
: config("SETTINGS::PAYMENTS:STRIPE:ENDPOINT_SECRET");
|
||||
}
|
||||
|
||||
|
||||
protected function createInvoice($user, $payment, $paymentStatus, $currencyCode)
|
||||
{
|
||||
$shopProduct = ShopProduct::where('id', $payment->shop_item_product_id)->first();
|
||||
//create invoice
|
||||
$lastInvoiceID = \App\Models\Invoice::where("invoice_name", "like", "%" . now()->format('mY') . "%")->count("id");
|
||||
$newInvoiceID = $lastInvoiceID + 1;
|
||||
$logoPath = storage_path('app/public/logo.png');
|
||||
|
||||
$seller = new Party([
|
||||
'name' => config("SETTINGS::INVOICE:COMPANY_NAME"),
|
||||
'phone' => config("SETTINGS::INVOICE:COMPANY_PHONE"),
|
||||
'address' => config("SETTINGS::INVOICE:COMPANY_ADDRESS"),
|
||||
'vat' => config("SETTINGS::INVOICE:COMPANY_VAT"),
|
||||
'custom_fields' => [
|
||||
'E-Mail' => config("SETTINGS::INVOICE:COMPANY_MAIL"),
|
||||
"Web" => config("SETTINGS::INVOICE:COMPANY_WEBSITE")
|
||||
],
|
||||
]);
|
||||
|
||||
|
||||
$customer = new Buyer([
|
||||
'name' => $user->name,
|
||||
'custom_fields' => [
|
||||
'E-Mail' => $user->email,
|
||||
'Client ID' => $user->id,
|
||||
],
|
||||
]);
|
||||
$item = (new InvoiceItem())
|
||||
->title($shopProduct->description)
|
||||
->pricePerUnit($shopProduct->price);
|
||||
|
||||
$notes = [
|
||||
__("Payment method") . ": " . $payment->payment_method,
|
||||
];
|
||||
$notes = implode("<br>", $notes);
|
||||
|
||||
|
||||
$invoice = Invoice::make()
|
||||
->template('controlpanel')
|
||||
->name(__("Invoice"))
|
||||
->buyer($customer)
|
||||
->seller($seller)
|
||||
->discountByPercent(0)
|
||||
->taxRate(floatval($shopProduct->getTaxPercent()))
|
||||
->shipping(0)
|
||||
->addItem($item)
|
||||
->status(__($paymentStatus))
|
||||
->series(now()->format('mY'))
|
||||
->delimiter("-")
|
||||
->sequence($newInvoiceID)
|
||||
->serialNumberFormat(config("SETTINGS::INVOICE:PREFIX") . '{DELIMITER}{SERIES}{SEQUENCE}')
|
||||
->currencyCode($currencyCode)
|
||||
->currencySymbol(Currencies::getSymbol($currencyCode))
|
||||
->notes($notes);
|
||||
|
||||
if (file_exists($logoPath)) {
|
||||
$invoice->logo($logoPath);
|
||||
}
|
||||
|
||||
//Save the invoice in "storage\app\invoice\USER_ID\YEAR"
|
||||
$invoice->filename = $invoice->getSerialNumber() . '.pdf';
|
||||
$invoice->render();
|
||||
Storage::disk("local")->put("invoice/" . $user->id . "/" . now()->format('Y') . "/" . $invoice->filename, $invoice->output);
|
||||
|
||||
|
||||
\App\Models\Invoice::create([
|
||||
'invoice_user' => $user->id,
|
||||
'invoice_name' => $invoice->getSerialNumber(),
|
||||
'payment_id' => $payment->payment_id,
|
||||
]);
|
||||
|
||||
//Send Invoice per Mail
|
||||
$user->notify(new InvoiceNotification($invoice, $user, $payment));
|
||||
return redirect()->route('store.index')->with('info', 'Payment was Canceled');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return JsonResponse|mixed
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function dataTable()
|
||||
|
@ -653,8 +143,9 @@ class PaymentController extends Controller
|
|||
$query = Payment::with('user');
|
||||
|
||||
return datatables($query)
|
||||
->editColumn('user', function (Payment $payment) {
|
||||
return $payment->user->name;
|
||||
|
||||
->addColumn('user', function (Payment $payment) {
|
||||
return ($payment->user) ? '<a href="' . route('admin.users.show', $payment->user->id) . '">' . $payment->user->name . '</a>' : __('Unknown user');
|
||||
})
|
||||
->editColumn('price', function (Payment $payment) {
|
||||
return $payment->formatToCurrency($payment->price);
|
||||
|
@ -670,12 +161,15 @@ class PaymentController extends Controller
|
|||
})
|
||||
|
||||
->editColumn('created_at', function (Payment $payment) {
|
||||
return $payment->created_at ? $payment->created_at->diffForHumans() : '';
|
||||
return [
|
||||
'display' => $payment->created_at ? $payment->created_at->diffForHumans() : '',
|
||||
'raw' => $payment->created_at ? strtotime($payment->created_at) : ''
|
||||
];
|
||||
})
|
||||
->addColumn('actions', function (Payment $payment) {
|
||||
return '<a data-content="' . __("Download") . '" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.invoices.downloadSingleInvoice', "id=" . $payment->payment_id) . '" class="btn btn-sm text-white btn-info mr-1"><i class="fas fa-file-download"></i></a>';
|
||||
return '<a data-content="' . __('Download') . '" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.invoices.downloadSingleInvoice', 'id=' . $payment->payment_id) . '" class="btn btn-sm text-white btn-info mr-1"><i class="fas fa-file-download"></i></a>';
|
||||
})
|
||||
->rawColumns(['actions'])
|
||||
->rawColumns(['actions', 'user'])
|
||||
->make(true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ use App\Http\Controllers\Controller;
|
|||
use App\Models\Location;
|
||||
use App\Models\Nest;
|
||||
use App\Models\Product;
|
||||
use App\Models\Settings;
|
||||
use Exception;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
|
@ -52,33 +51,33 @@ class ProductController extends Controller
|
|||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Request $request
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
"name" => "required|max:30",
|
||||
"price" => "required|numeric|max:1000000|min:0",
|
||||
"memory" => "required|numeric|max:1000000|min:5",
|
||||
"cpu" => "required|numeric|max:1000000|min:0",
|
||||
"swap" => "required|numeric|max:1000000|min:0",
|
||||
"description" => "required|string|max:191",
|
||||
"disk" => "required|numeric|max:1000000|min:5",
|
||||
"minimum_credits" => "required|numeric|max:1000000|min:-1",
|
||||
"io" => "required|numeric|max:1000000|min:0",
|
||||
"databases" => "required|numeric|max:1000000|min:0",
|
||||
"backups" => "required|numeric|max:1000000|min:0",
|
||||
"allocations" => "required|numeric|max:1000000|min:0",
|
||||
"nodes.*" => "required|exists:nodes,id",
|
||||
"eggs.*" => "required|exists:eggs,id",
|
||||
"disabled" => "nullable",
|
||||
'name' => 'required|max:30',
|
||||
'price' => 'required|numeric|max:1000000|min:0',
|
||||
'memory' => 'required|numeric|max:1000000|min:5',
|
||||
'cpu' => 'required|numeric|max:1000000|min:0',
|
||||
'swap' => 'required|numeric|max:1000000|min:0',
|
||||
'description' => 'required|string|max:191',
|
||||
'disk' => 'required|numeric|max:1000000|min:5',
|
||||
'minimum_credits' => 'required|numeric|max:1000000|min:-1',
|
||||
'io' => 'required|numeric|max:1000000|min:0',
|
||||
'databases' => 'required|numeric|max:1000000|min:0',
|
||||
'backups' => 'required|numeric|max:1000000|min:0',
|
||||
'allocations' => 'required|numeric|max:1000000|min:0',
|
||||
'nodes.*' => 'required|exists:nodes,id',
|
||||
'eggs.*' => 'required|exists:eggs,id',
|
||||
'disabled' => 'nullable',
|
||||
]);
|
||||
|
||||
$disabled = !is_null($request->input('disabled'));
|
||||
$disabled = ! is_null($request->input('disabled'));
|
||||
$product = Product::create(array_merge($request->all(), ['disabled' => $disabled]));
|
||||
|
||||
#link nodes and eggs
|
||||
//link nodes and eggs
|
||||
$product->eggs()->attach($request->input('eggs'));
|
||||
$product->nodes()->attach($request->input('nodes'));
|
||||
|
||||
|
@ -88,21 +87,21 @@ class ProductController extends Controller
|
|||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param Product $product
|
||||
* @param Product $product
|
||||
* @return Application|Factory|View
|
||||
*/
|
||||
public function show(Product $product)
|
||||
{
|
||||
return view('admin.products.show', [
|
||||
'product' => $product,
|
||||
'minimum_credits' => config("SETTINGS::USER:MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER"),
|
||||
'minimum_credits' => config('SETTINGS::USER:MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param Product $product
|
||||
* @param Product $product
|
||||
* @return Application|Factory|View
|
||||
*/
|
||||
public function edit(Product $product)
|
||||
|
@ -117,34 +116,34 @@ class ProductController extends Controller
|
|||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Product $product
|
||||
* @param Request $request
|
||||
* @param Product $product
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function update(Request $request, Product $product): RedirectResponse
|
||||
{
|
||||
$request->validate([
|
||||
"name" => "required|max:30",
|
||||
"price" => "required|numeric|max:1000000|min:0",
|
||||
"memory" => "required|numeric|max:1000000|min:5",
|
||||
"cpu" => "required|numeric|max:1000000|min:0",
|
||||
"swap" => "required|numeric|max:1000000|min:0",
|
||||
"description" => "required|string|max:191",
|
||||
"disk" => "required|numeric|max:1000000|min:5",
|
||||
"io" => "required|numeric|max:1000000|min:0",
|
||||
"minimum_credits" => "required|numeric|max:1000000|min:-1",
|
||||
"databases" => "required|numeric|max:1000000|min:0",
|
||||
"backups" => "required|numeric|max:1000000|min:0",
|
||||
"allocations" => "required|numeric|max:1000000|min:0",
|
||||
"nodes.*" => "required|exists:nodes,id",
|
||||
"eggs.*" => "required|exists:eggs,id",
|
||||
"disabled" => "nullable",
|
||||
'name' => 'required|max:30',
|
||||
'price' => 'required|numeric|max:1000000|min:0',
|
||||
'memory' => 'required|numeric|max:1000000|min:5',
|
||||
'cpu' => 'required|numeric|max:1000000|min:0',
|
||||
'swap' => 'required|numeric|max:1000000|min:0',
|
||||
'description' => 'required|string|max:191',
|
||||
'disk' => 'required|numeric|max:1000000|min:5',
|
||||
'io' => 'required|numeric|max:1000000|min:0',
|
||||
'minimum_credits' => 'required|numeric|max:1000000|min:-1',
|
||||
'databases' => 'required|numeric|max:1000000|min:0',
|
||||
'backups' => 'required|numeric|max:1000000|min:0',
|
||||
'allocations' => 'required|numeric|max:1000000|min:0',
|
||||
'nodes.*' => 'required|exists:nodes,id',
|
||||
'eggs.*' => 'required|exists:eggs,id',
|
||||
'disabled' => 'nullable',
|
||||
]);
|
||||
|
||||
$disabled = !is_null($request->input('disabled'));
|
||||
$disabled = ! is_null($request->input('disabled'));
|
||||
$product->update(array_merge($request->all(), ['disabled' => $disabled]));
|
||||
|
||||
#link nodes and eggs
|
||||
//link nodes and eggs
|
||||
$product->eggs()->detach();
|
||||
$product->nodes()->detach();
|
||||
$product->eggs()->attach($request->input('eggs'));
|
||||
|
@ -154,13 +153,13 @@ class ProductController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Product $product
|
||||
* @param Request $request
|
||||
* @param Product $product
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function disable(Request $request, Product $product)
|
||||
{
|
||||
$product->update(['disabled' => !$product->disabled]);
|
||||
$product->update(['disabled' => ! $product->disabled]);
|
||||
|
||||
return redirect()->route('admin.products.index')->with('success', 'Product has been updated!');
|
||||
}
|
||||
|
@ -168,7 +167,7 @@ class ProductController extends Controller
|
|||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param Product $product
|
||||
* @param Product $product
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function destroy(Product $product)
|
||||
|
@ -179,12 +178,13 @@ class ProductController extends Controller
|
|||
}
|
||||
|
||||
$product->delete();
|
||||
|
||||
return redirect()->back()->with('success', __('Product has been removed!'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return JsonResponse|mixed
|
||||
*
|
||||
* @throws Exception|Exception
|
||||
*/
|
||||
public function dataTable()
|
||||
|
@ -194,14 +194,14 @@ class ProductController extends Controller
|
|||
return datatables($query)
|
||||
->addColumn('actions', function (Product $product) {
|
||||
return '
|
||||
<a data-content="' . __("Show") . '" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.products.show', $product->id) . '" class="btn btn-sm text-white btn-warning mr-1"><i class="fas fa-eye"></i></a>
|
||||
<a data-content="' . __("Clone") . '" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.products.clone', $product->id) . '" class="btn btn-sm text-white btn-primary mr-1"><i class="fas fa-clone"></i></a>
|
||||
<a data-content="' . __("Edit") . '" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.products.edit', $product->id) . '" class="btn btn-sm btn-info mr-1"><i class="fas fa-pen"></i></a>
|
||||
<a data-content="'.__('Show').'" data-toggle="popover" data-trigger="hover" data-placement="top" href="'.route('admin.products.show', $product->id).'" class="btn btn-sm text-white btn-warning mr-1"><i class="fas fa-eye"></i></a>
|
||||
<a data-content="'.__('Clone').'" data-toggle="popover" data-trigger="hover" data-placement="top" href="'.route('admin.products.clone', $product->id).'" class="btn btn-sm text-white btn-primary mr-1"><i class="fas fa-clone"></i></a>
|
||||
<a data-content="'.__('Edit').'" data-toggle="popover" data-trigger="hover" data-placement="top" href="'.route('admin.products.edit', $product->id).'" class="btn btn-sm btn-info mr-1"><i class="fas fa-pen"></i></a>
|
||||
|
||||
<form class="d-inline" onsubmit="return submitResult();" method="post" action="' . route('admin.products.destroy', $product->id) . '">
|
||||
' . csrf_field() . '
|
||||
' . method_field("DELETE") . '
|
||||
<button data-content="' . __("Delete") . '" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm btn-danger mr-1"><i class="fas fa-trash"></i></button>
|
||||
<form class="d-inline" onsubmit="return submitResult();" method="post" action="'.route('admin.products.destroy', $product->id).'">
|
||||
'.csrf_field().'
|
||||
'.method_field('DELETE').'
|
||||
<button data-content="'.__('Delete').'" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm btn-danger mr-1"><i class="fas fa-trash"></i></button>
|
||||
</form>
|
||||
';
|
||||
})
|
||||
|
@ -216,18 +216,22 @@ class ProductController extends Controller
|
|||
return $product->eggs()->count();
|
||||
})
|
||||
->addColumn('disabled', function (Product $product) {
|
||||
$checked = $product->disabled == false ? "checked" : "";
|
||||
$checked = $product->disabled == false ? 'checked' : '';
|
||||
|
||||
return '
|
||||
<form class="d-inline" onsubmit="return submitResult();" method="post" action="' . route('admin.products.disable', $product->id) . '">
|
||||
' . csrf_field() . '
|
||||
' . method_field("PATCH") . '
|
||||
<form class="d-inline" onsubmit="return submitResult();" method="post" action="'.route('admin.products.disable', $product->id).'">
|
||||
'.csrf_field().'
|
||||
'.method_field('PATCH').'
|
||||
<div class="custom-control custom-switch">
|
||||
<input ' . $checked . ' name="disabled" onchange="this.form.submit()" type="checkbox" class="custom-control-input" id="switch' . $product->id . '">
|
||||
<label class="custom-control-label" for="switch' . $product->id . '"></label>
|
||||
<input '.$checked.' name="disabled" onchange="this.form.submit()" type="checkbox" class="custom-control-input" id="switch'.$product->id.'">
|
||||
<label class="custom-control-label" for="switch'.$product->id.'"></label>
|
||||
</div>
|
||||
</form>
|
||||
';
|
||||
})
|
||||
->editColumn('minimum_credits', function (Product $product) {
|
||||
return $product->minimum_credits==-1 ? config('SETTINGS::USER:MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER') : $product->minimum_credits;
|
||||
})
|
||||
->editColumn('created_at', function (Product $product) {
|
||||
return $product->created_at ? $product->created_at->diffForHumans() : '';
|
||||
})
|
||||
|
|
|
@ -3,10 +3,9 @@
|
|||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Classes\Pterodactyl;
|
||||
use App\Classes\PterodactylWrapper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Server;
|
||||
use App\Models\Settings;
|
||||
use App\Models\User;
|
||||
use Exception;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
|
@ -15,6 +14,7 @@ use Illuminate\Http\JsonResponse;
|
|||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class ServerController extends Controller
|
||||
{
|
||||
|
@ -28,66 +28,58 @@ class ServerController extends Controller
|
|||
return view('admin.servers.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param Server $server
|
||||
* @return Response
|
||||
*/
|
||||
public function show(Server $server)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param Server $server
|
||||
* @param Server $server
|
||||
* @return Response
|
||||
*/
|
||||
|
||||
public function edit(Server $server)
|
||||
{
|
||||
// get all users from the database
|
||||
$users = User::all();
|
||||
|
||||
return view('admin.servers.edit')->with([
|
||||
'server' => $server
|
||||
'server' => $server,
|
||||
'users' => $users,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Server $server
|
||||
* @return Response
|
||||
* @param Request $request
|
||||
* @param Server $server
|
||||
*/
|
||||
public function update(Request $request, Server $server)
|
||||
{
|
||||
$request->validate([
|
||||
"identifier" => "required|string",
|
||||
'identifier' => 'required|string',
|
||||
'user_id' => 'required|integer',
|
||||
]);
|
||||
|
||||
$server->update($request->all());
|
||||
|
||||
if ($request->get('user_id') != $server->user_id) {
|
||||
// find the user
|
||||
$user = User::findOrFail($request->get('user_id'));
|
||||
|
||||
// try to update the owner on pterodactyl
|
||||
try {
|
||||
$response = Pterodactyl::updateServerOwner($server, $user->pterodactyl_id);
|
||||
if ($response->getStatusCode() != 200) {
|
||||
return redirect()->back()->with('error', 'Failed to update server owner on pterodactyl');
|
||||
}
|
||||
|
||||
// update the owner on the database
|
||||
$server->user_id = $user->id;
|
||||
} catch (Exception $e) {
|
||||
return redirect()->back()->with('error', 'Internal Server Error');
|
||||
}
|
||||
}
|
||||
|
||||
// update the identifier
|
||||
$server->identifier = $request->get('identifier');
|
||||
$server->save();
|
||||
|
||||
return redirect()->route('admin.servers.index')->with('success', 'Server updated!');
|
||||
}
|
||||
|
@ -95,13 +87,14 @@ class ServerController extends Controller
|
|||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param Server $server
|
||||
* @param Server $server
|
||||
* @return RedirectResponse|Response
|
||||
*/
|
||||
public function destroy(Server $server)
|
||||
{
|
||||
try {
|
||||
$server->delete();
|
||||
|
||||
return redirect()->route('admin.servers.index')->with('success', __('Server removed'));
|
||||
} catch (Exception $e) {
|
||||
return redirect()->route('admin.servers.index')->with('error', __('An exception has occurred while trying to remove a resource "') . $e->getMessage() . '"');
|
||||
|
@ -109,13 +102,13 @@ class ServerController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
* @param Server $server
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function toggleSuspended(Server $server)
|
||||
{
|
||||
try {
|
||||
$server->isSuspended() ? $server->unSuspend() : $server->suspend();
|
||||
$server->isSuspended() ? $server->unSuspend() : $server->suspend();
|
||||
} catch (Exception $exception) {
|
||||
return redirect()->back()->with('error', $exception->getMessage());
|
||||
}
|
||||
|
@ -130,20 +123,20 @@ class ServerController extends Controller
|
|||
|
||||
$CPIDArray = [];
|
||||
$renameCount = 0;
|
||||
foreach($CPServers as $CPServer)//go thru all CP servers and make array with IDs as keys. All values are false.
|
||||
{
|
||||
if($CPServer->pterodactyl_id) $CPIDArray[$CPServer->pterodactyl_id] = false;
|
||||
foreach ($CPServers as $CPServer) { //go thru all CP servers and make array with IDs as keys. All values are false.
|
||||
if ($CPServer->pterodactyl_id) {
|
||||
$CPIDArray[$CPServer->pterodactyl_id] = false;
|
||||
}
|
||||
}
|
||||
|
||||
foreach($pteroServers as $server)//go thru all ptero servers, if server exists, change value to true in array.
|
||||
{
|
||||
if(isset($CPIDArray[$server['attributes']['id']])){
|
||||
$CPIDArray[$server['attributes']['id']]=true;
|
||||
foreach ($pteroServers as $server) { //go thru all ptero servers, if server exists, change value to true in array.
|
||||
if (isset($CPIDArray[$server['attributes']['id']])) {
|
||||
$CPIDArray[$server['attributes']['id']] = true;
|
||||
|
||||
if(isset($server['attributes']['name'])){//failsafe
|
||||
if (isset($server['attributes']['name'])) { //failsafe
|
||||
//Check if a server got renamed
|
||||
$savedServer = Server::query()->where('pterodactyl_id', $server['attributes']['id'])->first();
|
||||
if($savedServer->name != $server['attributes']['name']){
|
||||
if ($savedServer->name != $server['attributes']['name']) {
|
||||
$savedServer->name = $server['attributes']['name'];
|
||||
$savedServer->save();
|
||||
$renameCount++;
|
||||
|
@ -151,27 +144,39 @@ class ServerController extends Controller
|
|||
}
|
||||
}
|
||||
}
|
||||
$filteredArray = array_filter($CPIDArray, function($v, $k) { return $v == false; }, ARRAY_FILTER_USE_BOTH); //Array of servers, that dont exist on ptero (value == false)
|
||||
$filteredArray = array_filter($CPIDArray, function ($v, $k) {
|
||||
return $v == false;
|
||||
}, ARRAY_FILTER_USE_BOTH); //Array of servers, that dont exist on ptero (value == false)
|
||||
$deleteCount = 0;
|
||||
foreach($filteredArray as $key => $CPID)//delete servers that dont exist on ptero anymore
|
||||
{
|
||||
if(!Pterodactyl::getServerAttributes($key, true)) $deleteCount++;
|
||||
foreach ($filteredArray as $key => $CPID) { //delete servers that dont exist on ptero anymore
|
||||
if (!Pterodactyl::getServerAttributes($key, true)) {
|
||||
$deleteCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return redirect()->back()->with('success', __('Servers synced successfully' . (($renameCount)?(',\n' . __('renamed') . ' ' . $renameCount . ' ' . __('servers')):'') . ((count($filteredArray))?(',\n' . __('deleted') . ' ' . $deleteCount . '/' . count($filteredArray) . ' ' . __('old servers')):''))) . '.';
|
||||
return redirect()->back()->with('success', __('Servers synced successfully' . (($renameCount) ? (',\n' . __('renamed') . ' ' . $renameCount . ' ' . __('servers')) : '') . ((count($filteredArray)) ? (',\n' . __('deleted') . ' ' . $deleteCount . '/' . count($filteredArray) . ' ' . __('old servers')) : ''))) . '.';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return JsonResponse|mixed
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function dataTable(Request $request)
|
||||
{
|
||||
$query = Server::with(['user', 'product']);
|
||||
if ($request->has('product')) $query->where('product_id', '=', $request->input('product'));
|
||||
if ($request->has('user')) $query->where('user_id', '=', $request->input('user'));
|
||||
|
||||
|
||||
if ($request->has('product')) {
|
||||
$query->where('product_id', '=', $request->input('product'));
|
||||
}
|
||||
if ($request->has('user')) {
|
||||
$query->where('user_id', '=', $request->input('user'));
|
||||
}
|
||||
$query->select('servers.*');
|
||||
|
||||
Log::info($request->input('order'));
|
||||
|
||||
|
||||
return datatables($query)
|
||||
->addColumn('user', function (Server $server) {
|
||||
|
@ -181,12 +186,12 @@ class ServerController extends Controller
|
|||
return $server->product->description;
|
||||
})
|
||||
->addColumn('actions', function (Server $server) {
|
||||
$suspendColor = $server->isSuspended() ? "btn-success" : "btn-warning";
|
||||
$suspendIcon = $server->isSuspended() ? "fa-play-circle" : "fa-pause-circle";
|
||||
$suspendText = $server->isSuspended() ? __("Unsuspend") : __("Suspend");
|
||||
$suspendColor = $server->isSuspended() ? 'btn-success' : 'btn-warning';
|
||||
$suspendIcon = $server->isSuspended() ? 'fa-play-circle' : 'fa-pause-circle';
|
||||
$suspendText = $server->isSuspended() ? __('Unsuspend') : __('Suspend');
|
||||
|
||||
return '
|
||||
<a data-content="' . __("Edit") . '" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.servers.edit', $server->id) . '" class="btn btn-sm btn-info mr-1"><i class="fas fa-pen"></i></a>
|
||||
<a data-content="' . __('Edit') . '" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.servers.edit', $server->id) . '" class="btn btn-sm btn-info mr-1"><i class="fas fa-pen"></i></a>
|
||||
<form class="d-inline" method="post" action="' . route('admin.servers.togglesuspend', $server->id) . '">
|
||||
' . csrf_field() . '
|
||||
<button data-content="' . $suspendText . '" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm ' . $suspendColor . ' text-white mr-1"><i class="far ' . $suspendIcon . '"></i></button>
|
||||
|
@ -194,14 +199,15 @@ class ServerController extends Controller
|
|||
|
||||
<form class="d-inline" onsubmit="return submitResult();" method="post" action="' . route('admin.servers.destroy', $server->id) . '">
|
||||
' . csrf_field() . '
|
||||
' . method_field("DELETE") . '
|
||||
<button data-content="' . __("Delete") . '" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm btn-danger mr-1"><i class="fas fa-trash"></i></button>
|
||||
' . method_field('DELETE') . '
|
||||
<button data-content="' . __('Delete') . '" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm btn-danger mr-1"><i class="fas fa-trash"></i></button>
|
||||
</form>
|
||||
|
||||
';
|
||||
})
|
||||
->addColumn('status', function (Server $server) {
|
||||
$labelColor = $server->isSuspended() ? 'text-danger' : 'text-success';
|
||||
$labelColor = $server->suspended ? 'text-danger' : 'text-success';
|
||||
|
||||
return '<i class="fas ' . $labelColor . ' fa-circle mr-2"></i>';
|
||||
})
|
||||
->editColumn('created_at', function (Server $server) {
|
||||
|
@ -211,7 +217,7 @@ class ServerController extends Controller
|
|||
return $server->suspended ? $server->suspended->diffForHumans() : '';
|
||||
})
|
||||
->editColumn('name', function (Server $server) {
|
||||
return '<a class="text-info" target="_blank" href="' . config("SETTINGS::SYSTEM:PTERODACTYL:URL") . '/admin/servers/view/' . $server->pterodactyl_id . '">' . strip_tags($server->name) . '</a>';
|
||||
return '<a class="text-info" target="_blank" href="' . config('SETTINGS::SYSTEM:PTERODACTYL:URL') . '/admin/servers/view/' . $server->pterodactyl_id . '">' . strip_tags($server->name) . '</a>';
|
||||
})
|
||||
->rawColumns(['user', 'actions', 'status', 'name'])
|
||||
->make();
|
||||
|
|
|
@ -3,12 +3,11 @@
|
|||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Settings;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Qirolab\Theme\Theme;
|
||||
|
||||
class SettingsController extends Controller
|
||||
{
|
||||
|
@ -19,25 +18,38 @@ class SettingsController extends Controller
|
|||
*/
|
||||
public function index()
|
||||
{
|
||||
|
||||
|
||||
//Get all tabs as laravel view paths
|
||||
$tabs = [];
|
||||
foreach (glob(resource_path('views/admin/settings/tabs/*.blade.php')) as $filename) {
|
||||
$tabs[] = 'admin.settings.tabs.' . basename($filename, '.blade.php');
|
||||
if(file_exists(Theme::getViewPaths()[0] . '/admin/settings/tabs/')){
|
||||
$tabspath = glob(Theme::getViewPaths()[0] . '/admin/settings/tabs/*.blade.php');
|
||||
}else{
|
||||
$tabspath = glob(Theme::path($path = 'views', $themeName = 'default').'/admin/settings/tabs/*.blade.php');
|
||||
}
|
||||
|
||||
foreach ($tabspath as $filename) {
|
||||
$tabs[] = 'admin.settings.tabs.'.basename($filename, '.blade.php');
|
||||
}
|
||||
|
||||
|
||||
//Generate a html list item for each tab based on tabs file basename, set first tab as active
|
||||
$tabListItems = [];
|
||||
foreach ($tabs as $tab) {
|
||||
$tabName = str_replace('admin.settings.tabs.', '', $tab);
|
||||
$tabListItems[] = '<li class="nav-item">
|
||||
<a class="nav-link ' . (empty($tabListItems) ? 'active' : '') . '" data-toggle="pill" href="#' . $tabName . '">
|
||||
' . __(ucfirst($tabName)) . '
|
||||
<a class="nav-link '.(empty($tabListItems) ? 'active' : '').'" data-toggle="pill" href="#'.$tabName.'">
|
||||
'.__(ucfirst($tabName)).'
|
||||
</a></li>';
|
||||
}
|
||||
|
||||
$themes = array_diff(scandir(base_path('themes')), array('..', '.'));
|
||||
|
||||
return view('admin.settings.index', [
|
||||
'tabs' => $tabs,
|
||||
'tabListItems' => $tabListItems,
|
||||
'themes' => $themes,
|
||||
'active_theme' => Theme::active(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Models\ShopProduct;
|
||||
use App\Models\Settings;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Contracts\View\View;
|
||||
|
@ -15,6 +14,7 @@ use Illuminate\Validation\Rule;
|
|||
|
||||
class ShopProductController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
|
@ -26,12 +26,14 @@ class ShopProductController extends Controller
|
|||
|
||||
if (
|
||||
env('APP_ENV') == 'local' ||
|
||||
config("SETTINGS::PAYMENTS:PAYPAL:SECRET") && config("SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID") ||
|
||||
config("SETTINGS::PAYMENTS:STRIPE:SECRET") && config("SETTINGS::PAYMENTS:STRIPE:ENDPOINT_SECRET") && config("SETTINGS::PAYMENTS:STRIPE:METHODS")
|
||||
) $isPaymentSetup = true;
|
||||
config('SETTINGS::PAYMENTS:PAYPAL:SECRET') && config('SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID') ||
|
||||
config('SETTINGS::PAYMENTS:STRIPE:SECRET') && config('SETTINGS::PAYMENTS:STRIPE:ENDPOINT_SECRET') && config('SETTINGS::PAYMENTS:STRIPE:METHODS')
|
||||
) {
|
||||
$isPaymentSetup = true;
|
||||
}
|
||||
|
||||
return view('admin.store.index', [
|
||||
'isPaymentSetup' => $isPaymentSetup
|
||||
'isPaymentSetup' => $isPaymentSetup,
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -43,26 +45,26 @@ class ShopProductController extends Controller
|
|||
public function create()
|
||||
{
|
||||
return view('admin.store.create', [
|
||||
'currencyCodes' => config('currency_codes')
|
||||
'currencyCodes' => config('currency_codes'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Request $request
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
"disabled" => "nullable",
|
||||
"type" => "required|string",
|
||||
"currency_code" => ["required", "string", "max:3", Rule::in(config('currency_codes'))],
|
||||
"price" => "required|regex:/^\d+(\.\d{1,2})?$/",
|
||||
"quantity" => "required|numeric",
|
||||
"description" => "required|string|max:60",
|
||||
"display" => "required|string|max:60",
|
||||
'disabled' => 'nullable',
|
||||
'type' => 'required|string',
|
||||
'currency_code' => ['required', 'string', 'max:3', Rule::in(config('currency_codes'))],
|
||||
'price' => "required|regex:/^\d+(\.\d{1,2})?$/",
|
||||
'quantity' => 'required|numeric',
|
||||
'description' => 'required|string|max:60',
|
||||
'display' => 'required|string|max:60',
|
||||
]);
|
||||
|
||||
$disabled = !is_null($request->input('disabled'));
|
||||
|
@ -71,48 +73,37 @@ class ShopProductController extends Controller
|
|||
return redirect()->route('admin.store.index')->with('success', __('Store item has been created!'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param ShopProduct $shopProduct
|
||||
* @return Response
|
||||
*/
|
||||
public function show(ShopProduct $shopProduct)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param ShopProduct $shopProduct
|
||||
* @param ShopProduct $shopProduct
|
||||
* @return Application|Factory|View|Response
|
||||
*/
|
||||
public function edit(ShopProduct $shopProduct)
|
||||
{
|
||||
return view('admin.store.edit', [
|
||||
'currencyCodes' => config('currency_codes'),
|
||||
'shopProduct' => $shopProduct
|
||||
'shopProduct' => $shopProduct,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param ShopProduct $shopProduct
|
||||
* @param Request $request
|
||||
* @param ShopProduct $shopProduct
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function update(Request $request, ShopProduct $shopProduct)
|
||||
{
|
||||
$request->validate([
|
||||
"disabled" => "nullable",
|
||||
"type" => "required|string",
|
||||
"currency_code" => ["required", "string", "max:3", Rule::in(config('currency_codes'))],
|
||||
"price" => "required|regex:/^\d+(\.\d{1,2})?$/",
|
||||
"quantity" => "required|numeric|max:100000000",
|
||||
"description" => "required|string|max:60",
|
||||
"display" => "required|string|max:60",
|
||||
'disabled' => 'nullable',
|
||||
'type' => 'required|string',
|
||||
'currency_code' => ['required', 'string', 'max:3', Rule::in(config('currency_codes'))],
|
||||
'price' => "required|regex:/^\d+(\.\d{1,2})?$/",
|
||||
'quantity' => 'required|numeric|max:100000000',
|
||||
'description' => 'required|string|max:60',
|
||||
'display' => 'required|string|max:60',
|
||||
]);
|
||||
|
||||
$disabled = !is_null($request->input('disabled'));
|
||||
|
@ -122,8 +113,8 @@ class ShopProductController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param ShopProduct $shopProduct
|
||||
* @param Request $request
|
||||
* @param ShopProduct $shopProduct
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function disable(Request $request, ShopProduct $shopProduct)
|
||||
|
@ -136,38 +127,40 @@ class ShopProductController extends Controller
|
|||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param ShopProduct $shopProduct
|
||||
* @param ShopProduct $shopProduct
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function destroy(ShopProduct $shopProduct)
|
||||
{
|
||||
$shopProduct->delete();
|
||||
|
||||
return redirect()->back()->with('success', __('Store item has been removed!'));
|
||||
}
|
||||
|
||||
|
||||
public function dataTable()
|
||||
public function dataTable(Request $request)
|
||||
{
|
||||
$query = ShopProduct::query();
|
||||
|
||||
|
||||
return datatables($query)
|
||||
->addColumn('actions', function (ShopProduct $shopProduct) {
|
||||
return '
|
||||
<a data-content="' . __("Edit") . '" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.store.edit', $shopProduct->id) . '" class="btn btn-sm btn-info mr-1"><i class="fas fa-pen"></i></a>
|
||||
<a data-content="' . __('Edit') . '" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.store.edit', $shopProduct->id) . '" class="btn btn-sm btn-info mr-1"><i class="fas fa-pen"></i></a>
|
||||
|
||||
<form class="d-inline" onsubmit="return submitResult();" method="post" action="' . route('admin.store.destroy', $shopProduct->id) . '">
|
||||
' . csrf_field() . '
|
||||
' . method_field("DELETE") . '
|
||||
<button data-content="' . __("Delete") . '" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm btn-danger mr-1"><i class="fas fa-trash"></i></button>
|
||||
' . method_field('DELETE') . '
|
||||
<button data-content="' . __('Delete') . '" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm btn-danger mr-1"><i class="fas fa-trash"></i></button>
|
||||
</form>
|
||||
';
|
||||
})
|
||||
->addColumn('disabled', function (ShopProduct $shopProduct) {
|
||||
$checked = $shopProduct->disabled == false ? "checked" : "";
|
||||
$checked = $shopProduct->disabled == false ? 'checked' : '';
|
||||
|
||||
return '
|
||||
<form class="d-inline" onsubmit="return submitResult();" method="post" action="' . route('admin.store.disable', $shopProduct->id) . '">
|
||||
' . csrf_field() . '
|
||||
' . method_field("PATCH") . '
|
||||
' . method_field('PATCH') . '
|
||||
<div class="custom-control custom-switch">
|
||||
<input ' . $checked . ' name="disabled" onchange="this.form.submit()" type="checkbox" class="custom-control-input" id="switch' . $shopProduct->id . '">
|
||||
<label class="custom-control-label" for="switch' . $shopProduct->id . '"></label>
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Enums\UsefulLinkLocation;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\UsefulLink;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
|
@ -30,33 +31,41 @@ class UsefulLinkController extends Controller
|
|||
*/
|
||||
public function create()
|
||||
{
|
||||
return view('admin.usefullinks.create');
|
||||
$positions = UsefulLinkLocation::cases();
|
||||
return view('admin.usefullinks.create')->with('positions', $positions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Request $request
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
|
||||
$request->validate([
|
||||
'icon' => 'required|string',
|
||||
'title' => 'required|string|max:60',
|
||||
'link' => 'required|url|string|max:191',
|
||||
'description' => 'required|string|max:2000',
|
||||
'icon' => 'required|string',
|
||||
'title' => 'required|string|max:60',
|
||||
'link' => 'required|url|string|max:191',
|
||||
'description' => 'required|string|max:2000',
|
||||
]);
|
||||
|
||||
|
||||
UsefulLink::create([
|
||||
'icon' => $request->icon,
|
||||
'title' => $request->title,
|
||||
'link' => $request->link,
|
||||
'description' => $request->description,
|
||||
'position' => implode(",",$request->position),
|
||||
]);
|
||||
|
||||
UsefulLink::create($request->all());
|
||||
return redirect()->route('admin.usefullinks.index')->with('success', __('link has been created!'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param UsefulLink $usefullink
|
||||
* @param UsefulLink $usefullink
|
||||
* @return Response
|
||||
*/
|
||||
public function show(UsefulLink $usefullink)
|
||||
|
@ -67,21 +76,23 @@ class UsefulLinkController extends Controller
|
|||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param UsefulLink $usefullink
|
||||
* @param UsefulLink $usefullink
|
||||
* @return Application|Factory|View
|
||||
*/
|
||||
public function edit(UsefulLink $usefullink)
|
||||
{
|
||||
return view('admin.usefullinks.edit' , [
|
||||
'link' => $usefullink
|
||||
$positions = UsefulLinkLocation::cases();
|
||||
return view('admin.usefullinks.edit', [
|
||||
'link' => $usefullink,
|
||||
'positions' => $positions,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param UsefulLink $usefullink
|
||||
* @param Request $request
|
||||
* @param UsefulLink $usefullink
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function update(Request $request, UsefulLink $usefullink)
|
||||
|
@ -93,19 +104,27 @@ class UsefulLinkController extends Controller
|
|||
'description' => 'required|string|max:2000',
|
||||
]);
|
||||
|
||||
$usefullink->update($request->all());
|
||||
$usefullink->update([
|
||||
'icon' => $request->icon,
|
||||
'title' => $request->title,
|
||||
'link' => $request->link,
|
||||
'description' => $request->description,
|
||||
'position' => implode(",",$request->position),
|
||||
]);
|
||||
|
||||
return redirect()->route('admin.usefullinks.index')->with('success', __('link has been updated!'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param UsefulLink $usefullink
|
||||
* @param UsefulLink $usefullink
|
||||
* @return Response
|
||||
*/
|
||||
public function destroy(UsefulLink $usefullink)
|
||||
{
|
||||
$usefullink->delete();
|
||||
|
||||
return redirect()->back()->with('success', __('product has been removed!'));
|
||||
}
|
||||
|
||||
|
@ -116,12 +135,12 @@ class UsefulLinkController extends Controller
|
|||
return datatables($query)
|
||||
->addColumn('actions', function (UsefulLink $link) {
|
||||
return '
|
||||
<a data-content="'.__("Edit").'" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.usefullinks.edit', $link->id) . '" class="btn btn-sm btn-info mr-1"><i class="fas fa-pen"></i></a>
|
||||
<a data-content="'.__('Edit').'" data-toggle="popover" data-trigger="hover" data-placement="top" href="'.route('admin.usefullinks.edit', $link->id).'" class="btn btn-sm btn-info mr-1"><i class="fas fa-pen"></i></a>
|
||||
|
||||
<form class="d-inline" onsubmit="return submitResult();" method="post" action="' . route('admin.usefullinks.destroy', $link->id) . '">
|
||||
' . csrf_field() . '
|
||||
' . method_field("DELETE") . '
|
||||
<button data-content="'.__("Delete").'" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm btn-danger mr-1"><i class="fas fa-trash"></i></button>
|
||||
<form class="d-inline" onsubmit="return submitResult();" method="post" action="'.route('admin.usefullinks.destroy', $link->id).'">
|
||||
'.csrf_field().'
|
||||
'.method_field('DELETE').'
|
||||
<button data-content="'.__('Delete').'" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm btn-danger mr-1"><i class="fas fa-trash"></i></button>
|
||||
</form>
|
||||
';
|
||||
})
|
||||
|
@ -131,7 +150,7 @@ class UsefulLinkController extends Controller
|
|||
->editColumn('icon', function (UsefulLink $link) {
|
||||
return "<i class='{$link->icon}'></i>";
|
||||
})
|
||||
->rawColumns(['actions' , 'icon'])
|
||||
->rawColumns(['actions', 'icon'])
|
||||
->make();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,11 +5,8 @@ namespace App\Http\Controllers\Admin;
|
|||
use App\Classes\Pterodactyl;
|
||||
use App\Events\UserUpdateCreditsEvent;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Settings;
|
||||
use App\Models\User;
|
||||
use App\Notifications\DynamicNotification;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Spatie\QueryBuilder\QueryBuilder;
|
||||
use Exception;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
|
@ -19,14 +16,17 @@ use Illuminate\Http\Request;
|
|||
use Illuminate\Http\Response;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Illuminate\Support\HtmlString;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Spatie\QueryBuilder\QueryBuilder;
|
||||
|
||||
class UserController extends Controller
|
||||
{
|
||||
|
||||
private Pterodactyl $pterodactyl;
|
||||
|
||||
public function __construct(Pterodactyl $pterodactyl)
|
||||
|
@ -37,7 +37,7 @@ class UserController extends Controller
|
|||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Request $request
|
||||
* @return Application|Factory|View|Response
|
||||
*/
|
||||
public function index(Request $request)
|
||||
|
@ -48,23 +48,23 @@ class UserController extends Controller
|
|||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param User $user
|
||||
* @param User $user
|
||||
* @return Application|Factory|View|Response
|
||||
*/
|
||||
public function show(User $user)
|
||||
{
|
||||
//QUERY ALL REFERRALS A USER HAS
|
||||
//i am not proud of this at all.
|
||||
$allReferals = array();
|
||||
$referrals = DB::table("user_referrals")->where("referral_id","=",$user->id)->get();
|
||||
foreach($referrals as $referral){
|
||||
array_push($allReferals, $allReferals["id"] = User::query()->findOrFail($referral->registered_user_id));
|
||||
}
|
||||
array_pop($allReferals);
|
||||
$allReferals = [];
|
||||
$referrals = DB::table('user_referrals')->where('referral_id', '=', $user->id)->get();
|
||||
foreach ($referrals as $referral) {
|
||||
array_push($allReferals, $allReferals['id'] = User::query()->findOrFail($referral->registered_user_id));
|
||||
}
|
||||
array_pop($allReferals);
|
||||
|
||||
return view('admin.users.show')->with([
|
||||
'user' => $user,
|
||||
'referrals' => $allReferals
|
||||
'referrals' => $allReferals,
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -92,50 +92,51 @@ class UserController extends Controller
|
|||
return $item;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param User $user
|
||||
* @param User $user
|
||||
* @return Application|Factory|View|Response
|
||||
*/
|
||||
public function edit(User $user)
|
||||
{
|
||||
return view('admin.users.edit')->with([
|
||||
'user' => $user
|
||||
'user' => $user,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param User $user
|
||||
* @param Request $request
|
||||
* @param User $user
|
||||
* @return RedirectResponse
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function update(Request $request, User $user)
|
||||
{
|
||||
|
||||
$request->validate([
|
||||
"name" => "required|string|min:4|max:30",
|
||||
"pterodactyl_id" => "required|numeric|unique:users,pterodactyl_id,{$user->id}",
|
||||
"email" => "required|string|email",
|
||||
"credits" => "required|numeric|min:0|max:99999999",
|
||||
"server_limit" => "required|numeric|min:0|max:1000000",
|
||||
"role" => Rule::in(['admin', 'moderator', 'client', 'member']),
|
||||
"referral_code" => "required|string|min:2|max:32|unique:users,referral_code,{$user->id}",
|
||||
'name' => 'required|string|min:4|max:30',
|
||||
'pterodactyl_id' => "required|numeric|unique:users,pterodactyl_id,{$user->id}",
|
||||
'email' => 'required|string|email',
|
||||
'credits' => 'required|numeric|min:0|max:99999999',
|
||||
'server_limit' => 'required|numeric|min:0|max:1000000',
|
||||
'role' => Rule::in(['admin', 'moderator', 'client', 'member']),
|
||||
'referral_code' => "required|string|min:2|max:32|unique:users,referral_code,{$user->id}",
|
||||
]);
|
||||
|
||||
if (isset($this->pterodactyl->getUser($request->input('pterodactyl_id'))['errors'])) {
|
||||
throw ValidationException::withMessages([
|
||||
'pterodactyl_id' => [__("User does not exists on pterodactyl's panel")]
|
||||
'pterodactyl_id' => [__("User does not exists on pterodactyl's panel")],
|
||||
]);
|
||||
}
|
||||
|
||||
if (!is_null($request->input('new_password'))) {
|
||||
$request->validate([
|
||||
'new_password' => 'required|string|min:8',
|
||||
'new_password_confirmation' => 'required|same:new_password'
|
||||
'new_password_confirmation' => 'required|same:new_password',
|
||||
]);
|
||||
|
||||
$user->update([
|
||||
|
@ -152,53 +153,58 @@ class UserController extends Controller
|
|||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param User $user
|
||||
* @param User $user
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function destroy(User $user)
|
||||
{
|
||||
$user->delete();
|
||||
|
||||
return redirect()->back()->with('success', __('user has been removed!'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifys the users email
|
||||
*
|
||||
* @param User $user
|
||||
* @param User $user
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function verifyEmail(Request $request, User $user)
|
||||
{
|
||||
$user->verifyEmail();
|
||||
|
||||
return redirect()->back()->with('success', __('Email has been verified!'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param User $user
|
||||
* @param Request $request
|
||||
* @param User $user
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function loginAs(Request $request, User $user)
|
||||
{
|
||||
$request->session()->put('previousUser', Auth::user()->id);
|
||||
Auth::login($user);
|
||||
|
||||
return redirect()->route('home');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Request $request
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function logBackIn(Request $request)
|
||||
{
|
||||
Auth::loginUsingId($request->session()->get('previousUser'), true);
|
||||
$request->session()->remove('previousUser');
|
||||
|
||||
return redirect()->route('admin.users.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for seding notifications to the specified resource.
|
||||
*
|
||||
* @param User $user
|
||||
* @param User $user
|
||||
* @return Application|Factory|View|Response
|
||||
*/
|
||||
public function notifications(User $user)
|
||||
|
@ -209,44 +215,46 @@ class UserController extends Controller
|
|||
/**
|
||||
* Notify the specified resource.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param User $user
|
||||
* @param Request $request
|
||||
* @param User $user
|
||||
* @return RedirectResponse
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function notify(Request $request)
|
||||
{
|
||||
$data = $request->validate([
|
||||
"via" => "required|min:1|array",
|
||||
"via.*" => "required|string|in:mail,database",
|
||||
"all" => "required_without:users|boolean",
|
||||
"users" => "required_without:all|min:1|array",
|
||||
"users.*" => "exists:users,id",
|
||||
"title" => "required|string|min:1",
|
||||
"content" => "required|string|min:1"
|
||||
'via' => 'required|min:1|array',
|
||||
'via.*' => 'required|string|in:mail,database',
|
||||
'all' => 'required_without:users|boolean',
|
||||
'users' => 'required_without:all|min:1|array',
|
||||
'users.*' => 'exists:users,id',
|
||||
'title' => 'required|string|min:1',
|
||||
'content' => 'required|string|min:1',
|
||||
]);
|
||||
|
||||
$mail = null;
|
||||
$database = null;
|
||||
if (in_array('database', $data["via"])) {
|
||||
if (in_array('database', $data['via'])) {
|
||||
$database = [
|
||||
"title" => $data["title"],
|
||||
"content" => $data["content"]
|
||||
'title' => $data['title'],
|
||||
'content' => $data['content'],
|
||||
];
|
||||
}
|
||||
if (in_array('mail', $data["via"])) {
|
||||
if (in_array('mail', $data['via'])) {
|
||||
$mail = (new MailMessage)
|
||||
->subject($data["title"])
|
||||
->line(new HtmlString($data["content"]));
|
||||
->subject($data['title'])
|
||||
->line(new HtmlString($data['content']));
|
||||
}
|
||||
$all = $data["all"] ?? false;
|
||||
$users = $all ? User::all() : User::whereIn("id", $data["users"])->get();
|
||||
Notification::send($users, new DynamicNotification($data["via"], $database, $mail));
|
||||
$all = $data['all'] ?? false;
|
||||
$users = $all ? User::all() : User::whereIn('id', $data['users'])->get();
|
||||
Notification::send($users, new DynamicNotification($data['via'], $database, $mail));
|
||||
|
||||
return redirect()->route('admin.users.notifications')->with('success', __('Notification sent!'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
* @param User $user
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function toggleSuspended(User $user)
|
||||
|
@ -261,12 +269,14 @@ class UserController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function dataTable()
|
||||
public function dataTable(Request $request)
|
||||
{
|
||||
$query = User::with(['discordUser', 'servers'])->select('users.*');
|
||||
$query = User::with('discordUser')->withCount('servers');
|
||||
// manually count referrals in user_referrals table
|
||||
$query->selectRaw('users.*, (SELECT COUNT(*) FROM user_referrals WHERE user_referrals.referral_id = users.id) as referrals_count');
|
||||
|
||||
|
||||
return datatables($query)
|
||||
->addColumn('avatar', function (User $user) {
|
||||
|
@ -278,36 +288,28 @@ class UserController extends Controller
|
|||
->addColumn('verified', function (User $user) {
|
||||
return $user->getVerifiedStatus();
|
||||
})
|
||||
->addColumn('servers', function (User $user) {
|
||||
return $user->servers->count();
|
||||
})
|
||||
->addColumn('referrals', function (User $user) {
|
||||
return DB::table('user_referrals')->where("referral_id","=",$user->id)->count();
|
||||
})
|
||||
->addColumn('discordId', function (User $user) {
|
||||
return $user->discordUser ? $user->discordUser->id : '';
|
||||
})
|
||||
->addColumn('last_seen', function (User $user) {
|
||||
return $user->last_seen ? $user->last_seen->diffForHumans() : '';
|
||||
})
|
||||
->addColumn('actions', function (User $user) {
|
||||
$suspendColor = $user->isSuspended() ? "btn-success" : "btn-warning";
|
||||
$suspendIcon = $user->isSuspended() ? "fa-play-circle" : "fa-pause-circle";
|
||||
$suspendText = $user->isSuspended() ? __("Unsuspend") : __("Suspend");
|
||||
$suspendColor = $user->isSuspended() ? 'btn-success' : 'btn-warning';
|
||||
$suspendIcon = $user->isSuspended() ? 'fa-play-circle' : 'fa-pause-circle';
|
||||
$suspendText = $user->isSuspended() ? __('Unsuspend') : __('Suspend');
|
||||
|
||||
return '
|
||||
<a data-content="' . __("Login as User") . '" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.users.loginas', $user->id) . '" class="btn btn-sm btn-primary mr-1"><i class="fas fa-sign-in-alt"></i></a>
|
||||
<a data-content="' . __("Verify") . '" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.users.verifyEmail', $user->id) . '" class="btn btn-sm btn-secondary mr-1"><i class="fas fa-envelope"></i></a>
|
||||
<a data-content="' . __("Show") . '" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.users.show', $user->id) . '" class="btn btn-sm text-white btn-warning mr-1"><i class="fas fa-eye"></i></a>
|
||||
<a data-content="' . __("Edit") . '" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.users.edit', $user->id) . '" class="btn btn-sm btn-info mr-1"><i class="fas fa-pen"></i></a>
|
||||
<form class="d-inline" method="post" action="' . route('admin.users.togglesuspend', $user->id) . '">
|
||||
' . csrf_field() . '
|
||||
<button data-content="' . $suspendText . '" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm ' . $suspendColor . ' text-white mr-1"><i class="far ' . $suspendIcon . '"></i></button>
|
||||
</form>
|
||||
<a data-content="' . __('Login as User') . '" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.users.loginas', $user->id) . '" class="btn btn-sm btn-primary mr-1"><i class="fas fa-sign-in-alt"></i></a>
|
||||
<a data-content="' . __('Verify') . '" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.users.verifyEmail', $user->id) . '" class="btn btn-sm btn-secondary mr-1"><i class="fas fa-envelope"></i></a>
|
||||
<a data-content="' . __('Show') . '" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.users.show', $user->id) . '" class="btn btn-sm text-white btn-warning mr-1"><i class="fas fa-eye"></i></a>
|
||||
<a data-content="' . __('Edit') . '" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.users.edit', $user->id) . '" class="btn btn-sm btn-info mr-1"><i class="fas fa-pen"></i></a>
|
||||
<form class="d-inline" method="post" action="' . route('admin.users.togglesuspend', $user->id) . '">
|
||||
' . csrf_field() . '
|
||||
<button data-content="' . $suspendText . '" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm ' . $suspendColor . ' text-white mr-1"><i class="far ' . $suspendIcon . '"></i></button>
|
||||
</form>
|
||||
<form class="d-inline" onsubmit="return submitResult();" method="post" action="' . route('admin.users.destroy', $user->id) . '">
|
||||
' . csrf_field() . '
|
||||
' . method_field("DELETE") . '
|
||||
<button data-content="' . __("Delete") . '" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm btn-danger mr-1"><i class="fas fa-trash"></i></button>
|
||||
</form>
|
||||
' . csrf_field() . '
|
||||
' . method_field('DELETE') . '
|
||||
<button data-content="' . __('Delete') . '" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm btn-danger mr-1"><i class="fas fa-trash"></i></button>
|
||||
</form>
|
||||
';
|
||||
})
|
||||
->editColumn('role', function (User $user) {
|
||||
|
@ -328,13 +330,13 @@ class UserController extends Controller
|
|||
|
||||
return '<span class="badge ' . $badgeColor . '">' . $user->role . '</span>';
|
||||
})
|
||||
->editColumn('last_seen', function (User $user) {
|
||||
return $user->last_seen ? $user->last_seen->diffForHumans() : __('Never');
|
||||
})
|
||||
->editColumn('name', function (User $user) {
|
||||
return '<a class="text-info" target="_blank" href="' . config("SETTINGS::SYSTEM:PTERODACTYL:URL") . '/admin/users/view/' . $user->pterodactyl_id . '">' . strip_tags($user->name) . '</a>';
|
||||
return '<a class="text-info" target="_blank" href="' . config('SETTINGS::SYSTEM:PTERODACTYL:URL') . '/admin/users/view/' . $user->pterodactyl_id . '">' . strip_tags($user->name) . '</a>';
|
||||
})
|
||||
->orderColumn('last_seen', function ($query) {
|
||||
$query->orderBy('last_seen', "desc");
|
||||
})
|
||||
->rawColumns(['avatar', 'name', 'credits', 'role', 'usage', 'referrals', 'actions', 'last_seen'])
|
||||
->make(true);
|
||||
->rawColumns(['avatar', 'name', 'credits', 'role', 'usage', 'actions'])
|
||||
->make();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,16 +40,16 @@ class VoucherController extends Controller
|
|||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Request $request
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'memo' => 'nullable|string|max:191',
|
||||
'code' => 'required|string|alpha_dash|max:36|min:4|unique:vouchers',
|
||||
'uses' => 'required|numeric|max:2147483647|min:1',
|
||||
'credits' => 'required|numeric|between:0,99999999',
|
||||
'memo' => 'nullable|string|max:191',
|
||||
'code' => 'required|string|alpha_dash|max:36|min:4|unique:vouchers',
|
||||
'uses' => 'required|numeric|max:2147483647|min:1',
|
||||
'credits' => 'required|numeric|between:0,99999999',
|
||||
'expires_at' => 'nullable|multiple_date_format:d-m-Y H:i:s,d-m-Y|after:now|before:10 years',
|
||||
]);
|
||||
|
||||
|
@ -61,7 +61,7 @@ class VoucherController extends Controller
|
|||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param Voucher $voucher
|
||||
* @param Voucher $voucher
|
||||
* @return Response
|
||||
*/
|
||||
public function show(Voucher $voucher)
|
||||
|
@ -72,30 +72,30 @@ class VoucherController extends Controller
|
|||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param Voucher $voucher
|
||||
* @param Voucher $voucher
|
||||
* @return Application|Factory|View
|
||||
*/
|
||||
public function edit(Voucher $voucher)
|
||||
{
|
||||
return view('admin.vouchers.edit', [
|
||||
'voucher' => $voucher
|
||||
'voucher' => $voucher,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Voucher $voucher
|
||||
* @param Request $request
|
||||
* @param Voucher $voucher
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function update(Request $request, Voucher $voucher)
|
||||
{
|
||||
$request->validate([
|
||||
'memo' => 'nullable|string|max:191',
|
||||
'code' => "required|string|alpha_dash|max:36|min:4|unique:vouchers,code,{$voucher->id}",
|
||||
'uses' => 'required|numeric|max:2147483647|min:1',
|
||||
'credits' => 'required|numeric|between:0,99999999',
|
||||
'memo' => 'nullable|string|max:191',
|
||||
'code' => "required|string|alpha_dash|max:36|min:4|unique:vouchers,code,{$voucher->id}",
|
||||
'uses' => 'required|numeric|max:2147483647|min:1',
|
||||
'credits' => 'required|numeric|between:0,99999999',
|
||||
'expires_at' => 'nullable|multiple_date_format:d-m-Y H:i:s,d-m-Y|after:now|before:10 years',
|
||||
]);
|
||||
|
||||
|
@ -107,61 +107,71 @@ class VoucherController extends Controller
|
|||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param Voucher $voucher
|
||||
* @param Voucher $voucher
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function destroy(Voucher $voucher)
|
||||
{
|
||||
$voucher->delete();
|
||||
|
||||
return redirect()->back()->with('success', __('voucher has been removed!'));
|
||||
}
|
||||
|
||||
public function users(Voucher $voucher)
|
||||
{
|
||||
return view('admin.vouchers.users', [
|
||||
'voucher' => $voucher
|
||||
'voucher' => $voucher,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Request $request
|
||||
* @return JsonResponse
|
||||
*
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function redeem(Request $request)
|
||||
{
|
||||
#general validations
|
||||
//general validations
|
||||
$request->validate([
|
||||
'code' => 'required|exists:vouchers,code'
|
||||
'code' => 'required|exists:vouchers,code',
|
||||
]);
|
||||
|
||||
#get voucher by code
|
||||
//get voucher by code
|
||||
$voucher = Voucher::where('code', '=', $request->input('code'))->firstOrFail();
|
||||
|
||||
#extra validations
|
||||
if ($voucher->getStatus() == 'USES_LIMIT_REACHED') throw ValidationException::withMessages([
|
||||
'code' => __('This voucher has reached the maximum amount of uses')
|
||||
]);
|
||||
//extra validations
|
||||
if ($voucher->getStatus() == 'USES_LIMIT_REACHED') {
|
||||
throw ValidationException::withMessages([
|
||||
'code' => __('This voucher has reached the maximum amount of uses'),
|
||||
]);
|
||||
}
|
||||
|
||||
if ($voucher->getStatus() == 'EXPIRED') throw ValidationException::withMessages([
|
||||
'code' => __('This voucher has expired')
|
||||
]);
|
||||
if ($voucher->getStatus() == 'EXPIRED') {
|
||||
throw ValidationException::withMessages([
|
||||
'code' => __('This voucher has expired'),
|
||||
]);
|
||||
}
|
||||
|
||||
if (!$request->user()->vouchers()->where('id', '=', $voucher->id)->get()->isEmpty()) throw ValidationException::withMessages([
|
||||
'code' => __('You already redeemed this voucher code')
|
||||
]);
|
||||
if (! $request->user()->vouchers()->where('id', '=', $voucher->id)->get()->isEmpty()) {
|
||||
throw ValidationException::withMessages([
|
||||
'code' => __('You already redeemed this voucher code'),
|
||||
]);
|
||||
}
|
||||
|
||||
if ($request->user()->credits + $voucher->credits >= 99999999) throw ValidationException::withMessages([
|
||||
'code' => "You can't redeem this voucher because you would exceed the limit of " . CREDITS_DISPLAY_NAME
|
||||
]);
|
||||
if ($request->user()->credits + $voucher->credits >= 99999999) {
|
||||
throw ValidationException::withMessages([
|
||||
'code' => "You can't redeem this voucher because you would exceed the limit of ".CREDITS_DISPLAY_NAME,
|
||||
]);
|
||||
}
|
||||
|
||||
#redeem voucher
|
||||
//redeem voucher
|
||||
$voucher->redeem($request->user());
|
||||
|
||||
event(new UserUpdateCreditsEvent($request->user()));
|
||||
|
||||
return response()->json([
|
||||
'success' => "{$voucher->credits} " . CREDITS_DISPLAY_NAME ." ". __("have been added to your balance!")
|
||||
'success' => "{$voucher->credits} ".CREDITS_DISPLAY_NAME.' '.__('have been added to your balance!'),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -171,10 +181,10 @@ class VoucherController extends Controller
|
|||
|
||||
return datatables($users)
|
||||
->editColumn('name', function (User $user) {
|
||||
return '<a class="text-info" target="_blank" href="' . route('admin.users.show', $user->id) . '">' . $user->name . '</a>';
|
||||
return '<a class="text-info" target="_blank" href="'.route('admin.users.show', $user->id).'">'.$user->name.'</a>';
|
||||
})
|
||||
->addColumn('credits', function (User $user) {
|
||||
return '<i class="fas fa-coins mr-2"></i> ' . $user->credits();
|
||||
return '<i class="fas fa-coins mr-2"></i> '.$user->credits();
|
||||
})
|
||||
->addColumn('last_seen', function (User $user) {
|
||||
return $user->last_seen ? $user->last_seen->diffForHumans() : '';
|
||||
|
@ -182,6 +192,7 @@ class VoucherController extends Controller
|
|||
->rawColumns(['name', 'credits', 'last_seen'])
|
||||
->make();
|
||||
}
|
||||
|
||||
public function dataTable()
|
||||
{
|
||||
$query = Voucher::query();
|
||||
|
@ -189,20 +200,23 @@ class VoucherController extends Controller
|
|||
return datatables($query)
|
||||
->addColumn('actions', function (Voucher $voucher) {
|
||||
return '
|
||||
<a data-content="'.__("Users").'" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.vouchers.users', $voucher->id) . '" class="btn btn-sm btn-primary mr-1"><i class="fas fa-users"></i></a>
|
||||
<a data-content="'.__("Edit").'" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.vouchers.edit', $voucher->id) . '" class="btn btn-sm btn-info mr-1"><i class="fas fa-pen"></i></a>
|
||||
<a data-content="'.__('Users').'" data-toggle="popover" data-trigger="hover" data-placement="top" href="'.route('admin.vouchers.users', $voucher->id).'" class="btn btn-sm btn-primary mr-1"><i class="fas fa-users"></i></a>
|
||||
<a data-content="'.__('Edit').'" data-toggle="popover" data-trigger="hover" data-placement="top" href="'.route('admin.vouchers.edit', $voucher->id).'" class="btn btn-sm btn-info mr-1"><i class="fas fa-pen"></i></a>
|
||||
|
||||
<form class="d-inline" onsubmit="return submitResult();" method="post" action="' . route('admin.vouchers.destroy', $voucher->id) . '">
|
||||
' . csrf_field() . '
|
||||
' . method_field("DELETE") . '
|
||||
<button data-content="'.__("Delete").'" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm btn-danger mr-1"><i class="fas fa-trash"></i></button>
|
||||
<form class="d-inline" onsubmit="return submitResult();" method="post" action="'.route('admin.vouchers.destroy', $voucher->id).'">
|
||||
'.csrf_field().'
|
||||
'.method_field('DELETE').'
|
||||
<button data-content="'.__('Delete').'" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm btn-danger mr-1"><i class="fas fa-trash"></i></button>
|
||||
</form>
|
||||
';
|
||||
})
|
||||
->addColumn('status', function (Voucher $voucher) {
|
||||
$color = 'success';
|
||||
if ($voucher->getStatus() != __('VALID')) $color = 'danger';
|
||||
return '<span class="badge badge-' . $color . '">' . $voucher->getStatus() . '</span>';
|
||||
if ($voucher->getStatus() != __('VALID')) {
|
||||
$color = 'danger';
|
||||
}
|
||||
|
||||
return '<span class="badge badge-'.$color.'">'.$voucher->getStatus().'</span>';
|
||||
})
|
||||
->editColumn('uses', function (Voucher $voucher) {
|
||||
return "{$voucher->used} / {$voucher->uses}";
|
||||
|
@ -211,7 +225,10 @@ class VoucherController extends Controller
|
|||
return number_format($voucher->credits, 2, '.', '');
|
||||
})
|
||||
->editColumn('expires_at', function (Voucher $voucher) {
|
||||
if (!$voucher->expires_at) return "";
|
||||
if (! $voucher->expires_at) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $voucher->expires_at ? $voucher->expires_at->diffForHumans() : '';
|
||||
})
|
||||
->editColumn('code', function (Voucher $voucher) {
|
||||
|
|
|
@ -19,8 +19,9 @@ class NotificationController extends Controller
|
|||
{
|
||||
/**
|
||||
* Display all notifications of an user.
|
||||
* @param Request $request
|
||||
* @param int $userId
|
||||
*
|
||||
* @param Request $request
|
||||
* @param int $userId
|
||||
* @return Response
|
||||
*/
|
||||
public function index(Request $request, int $userId)
|
||||
|
@ -28,14 +29,14 @@ class NotificationController extends Controller
|
|||
$discordUser = DiscordUser::find($userId);
|
||||
$user = $discordUser ? $discordUser->user : User::findOrFail($userId);
|
||||
|
||||
return $user->notifications()->paginate($request->query("per_page", 50));
|
||||
return $user->notifications()->paginate($request->query('per_page', 50));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a specific notification
|
||||
*
|
||||
* @param int $userId
|
||||
* @param int $notificationId
|
||||
* @param int $userId
|
||||
* @param int $notificationId
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function view(int $userId, $notificationId)
|
||||
|
@ -43,10 +44,10 @@ class NotificationController extends Controller
|
|||
$discordUser = DiscordUser::find($userId);
|
||||
$user = $discordUser ? $discordUser->user : User::findOrFail($userId);
|
||||
|
||||
$notification = $user->notifications()->where("id", $notificationId)->get()->first();
|
||||
$notification = $user->notifications()->where('id', $notificationId)->get()->first();
|
||||
|
||||
if (!$notification) {
|
||||
return response()->json(["message" => "Notification not found."], 404);
|
||||
if (! $notification) {
|
||||
return response()->json(['message' => 'Notification not found.'], 404);
|
||||
}
|
||||
|
||||
return $notification;
|
||||
|
@ -55,42 +56,43 @@ class NotificationController extends Controller
|
|||
/**
|
||||
* Send a notification to an user.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Request $request
|
||||
* @return JsonResponse
|
||||
*
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function send(Request $request)
|
||||
{
|
||||
$data = $request->validate([
|
||||
"via" => ["required", new Delimited("in:mail,database")],
|
||||
"all" => "required_without:users|boolean",
|
||||
"users" => ["required_without:all"],
|
||||
"title" => "required|string|min:1",
|
||||
"content" => "required|string|min:1"
|
||||
'via' => ['required', new Delimited('in:mail,database')],
|
||||
'all' => 'required_without:users|boolean',
|
||||
'users' => ['required_without:all'],
|
||||
'title' => 'required|string|min:1',
|
||||
'content' => 'required|string|min:1',
|
||||
]);
|
||||
$via = explode(",", $data["via"]);
|
||||
$via = explode(',', $data['via']);
|
||||
$mail = null;
|
||||
$database = null;
|
||||
|
||||
if (in_array("database", $via)) {
|
||||
if (in_array('database', $via)) {
|
||||
$database = [
|
||||
"title" => $data["title"],
|
||||
"content" => $data["content"]
|
||||
'title' => $data['title'],
|
||||
'content' => $data['content'],
|
||||
];
|
||||
}
|
||||
if (in_array("mail", $via)) {
|
||||
if (in_array('mail', $via)) {
|
||||
$mail = (new MailMessage)
|
||||
->subject($data["title"])
|
||||
->line(new HtmlString($data["content"]));
|
||||
->subject($data['title'])
|
||||
->line(new HtmlString($data['content']));
|
||||
}
|
||||
|
||||
$all = $data["all"] ?? false;
|
||||
$all = $data['all'] ?? false;
|
||||
if ($all) {
|
||||
$users = User::all();
|
||||
} else {
|
||||
$userIds = explode(",", $data["users"]);
|
||||
$userIds = explode(',', $data['users']);
|
||||
$users = User::query()
|
||||
->whereIn("id", $userIds)
|
||||
->whereIn('id', $userIds)
|
||||
->orWhereHas('discordUser', function (Builder $builder) use ($userIds) {
|
||||
$builder->whereIn('id', $userIds);
|
||||
})
|
||||
|
@ -104,13 +106,14 @@ class NotificationController extends Controller
|
|||
}
|
||||
|
||||
Notification::send($users, new DynamicNotification($via, $database, $mail));
|
||||
return response()->json(["message" => "Notification successfully sent.", 'user_count' => $users->count()]);
|
||||
|
||||
return response()->json(['message' => 'Notification successfully sent.', 'user_count' => $users->count()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all notifications from an user
|
||||
*
|
||||
* @param int $userId
|
||||
* @param int $userId
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function delete(int $userId)
|
||||
|
@ -120,15 +123,14 @@ class NotificationController extends Controller
|
|||
|
||||
$count = $user->notifications()->delete();
|
||||
|
||||
return response()->json(["message" => "All notifications have been successfully deleted.", "count" => $count]);
|
||||
return response()->json(['message' => 'All notifications have been successfully deleted.', 'count' => $count]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete a specific notification
|
||||
*
|
||||
* @param int $userId
|
||||
* @param int $notificationId
|
||||
* @param int $userId
|
||||
* @param int $notificationId
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function deleteOne(int $userId, $notificationid)
|
||||
|
@ -136,13 +138,14 @@ class NotificationController extends Controller
|
|||
$discordUser = DiscordUser::find($userId);
|
||||
$user = $discordUser ? $discordUser->user : User::findOrFail($userId);
|
||||
|
||||
$notification = $user->notifications()->where("id", $notificationid)->get()->first();
|
||||
$notification = $user->notifications()->where('id', $notificationid)->get()->first();
|
||||
|
||||
if (!$notification) {
|
||||
return response()->json(["message" => "Notification not found."], 404);
|
||||
if (! $notification) {
|
||||
return response()->json(['message' => 'Notification not found.'], 404);
|
||||
}
|
||||
|
||||
$notification->delete();
|
||||
|
||||
return response()->json($notification);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,12 +15,13 @@ use Spatie\QueryBuilder\QueryBuilder;
|
|||
class ServerController extends Controller
|
||||
{
|
||||
public const ALLOWED_INCLUDES = ['product', 'user'];
|
||||
|
||||
public const ALLOWED_FILTERS = ['name', 'suspended', 'identifier', 'pterodactyl_id', 'user_id', 'product_id'];
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Request $request
|
||||
* @return LengthAwarePaginator
|
||||
*/
|
||||
public function index(Request $request)
|
||||
|
@ -35,8 +36,7 @@ class ServerController extends Controller
|
|||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param Server $server
|
||||
*
|
||||
* @param Server $server
|
||||
* @return Server|Collection|Model
|
||||
*/
|
||||
public function show(Server $server)
|
||||
|
@ -51,19 +51,20 @@ class ServerController extends Controller
|
|||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param Server $server
|
||||
* @param Server $server
|
||||
* @return Server
|
||||
*/
|
||||
public function destroy(Server $server)
|
||||
{
|
||||
$server->delete();
|
||||
|
||||
return $server;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* suspend server
|
||||
* @param Server $server
|
||||
*
|
||||
* @param Server $server
|
||||
* @return Server|JsonResponse
|
||||
*/
|
||||
public function suspend(Server $server)
|
||||
|
@ -77,10 +78,10 @@ class ServerController extends Controller
|
|||
return $server->load('product');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* unsuspend server
|
||||
* @param Server $server
|
||||
*
|
||||
* @param Server $server
|
||||
* @return Server|JsonResponse
|
||||
*/
|
||||
public function unSuspend(Server $server)
|
||||
|
|
|
@ -6,9 +6,9 @@ use App\Classes\Pterodactyl;
|
|||
use App\Events\UserUpdateCreditsEvent;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\DiscordUser;
|
||||
use App\Models\Settings;
|
||||
use App\Models\User;
|
||||
use App\Notifications\ReferralNotification;
|
||||
use App\Traits\Referral;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||
|
@ -28,13 +28,16 @@ use Spatie\QueryBuilder\QueryBuilder;
|
|||
|
||||
class UserController extends Controller
|
||||
{
|
||||
use Referral;
|
||||
|
||||
const ALLOWED_INCLUDES = ['servers', 'notifications', 'payments', 'vouchers', 'discordUser'];
|
||||
|
||||
const ALLOWED_FILTERS = ['name', 'server_limit', 'email', 'pterodactyl_id', 'role', 'suspended'];
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Request $request
|
||||
* @return LengthAwarePaginator
|
||||
*/
|
||||
public function index(Request $request)
|
||||
|
@ -46,12 +49,10 @@ class UserController extends Controller
|
|||
return $query->paginate($request->input('per_page') ?? 50);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @param int $id
|
||||
* @return User|Builder|Collection|Model
|
||||
*/
|
||||
public function show(int $id)
|
||||
|
@ -70,12 +71,11 @@ class UserController extends Controller
|
|||
return $query->firstOrFail();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param int $id
|
||||
* @param Request $request
|
||||
* @param int $id
|
||||
* @return User
|
||||
*/
|
||||
public function update(Request $request, int $id)
|
||||
|
@ -84,11 +84,11 @@ class UserController extends Controller
|
|||
$user = $discordUser ? $discordUser->user : User::findOrFail($id);
|
||||
|
||||
$request->validate([
|
||||
"name" => "sometimes|string|min:4|max:30",
|
||||
"email" => "sometimes|string|email",
|
||||
"credits" => "sometimes|numeric|min:0|max:1000000",
|
||||
"server_limit" => "sometimes|numeric|min:0|max:1000000",
|
||||
"role" => ['sometimes', Rule::in(['admin', 'moderator', 'client', 'member'])],
|
||||
'name' => 'sometimes|string|min:4|max:30',
|
||||
'email' => 'sometimes|string|email',
|
||||
'credits' => 'sometimes|numeric|min:0|max:1000000',
|
||||
'server_limit' => 'sometimes|numeric|min:0|max:1000000',
|
||||
'role' => ['sometimes', Rule::in(['admin', 'moderator', 'client', 'member'])],
|
||||
]);
|
||||
|
||||
event(new UserUpdateCreditsEvent($user));
|
||||
|
@ -96,16 +96,16 @@ class UserController extends Controller
|
|||
//Update Users Password on Pterodactyl
|
||||
//Username,Mail,First and Lastname are required aswell
|
||||
$response = Pterodactyl::client()->patch('/application/users/' . $user->pterodactyl_id, [
|
||||
"username" => $request->name,
|
||||
"first_name" => $request->name,
|
||||
"last_name" => $request->name,
|
||||
"email" => $request->email,
|
||||
'username' => $request->name,
|
||||
'first_name' => $request->name,
|
||||
'last_name' => $request->name,
|
||||
'email' => $request->email,
|
||||
|
||||
]);
|
||||
if ($response->failed()) {
|
||||
throw ValidationException::withMessages([
|
||||
'pterodactyl_error_message' => $response->toException()->getMessage(),
|
||||
'pterodactyl_error_status' => $response->toException()->getCode()
|
||||
'pterodactyl_error_status' => $response->toException()->getCode(),
|
||||
]);
|
||||
}
|
||||
$user->update($request->all());
|
||||
|
@ -116,9 +116,10 @@ class UserController extends Controller
|
|||
/**
|
||||
* increments the users credits or/and server_limit
|
||||
*
|
||||
* @param Request $request
|
||||
* @param int $id
|
||||
* @param Request $request
|
||||
* @param int $id
|
||||
* @return User
|
||||
*
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function increment(Request $request, int $id)
|
||||
|
@ -127,22 +128,26 @@ class UserController extends Controller
|
|||
$user = $discordUser ? $discordUser->user : User::findOrFail($id);
|
||||
|
||||
$request->validate([
|
||||
"credits" => "sometimes|numeric|min:0|max:1000000",
|
||||
"server_limit" => "sometimes|numeric|min:0|max:1000000",
|
||||
'credits' => 'sometimes|numeric|min:0|max:1000000',
|
||||
'server_limit' => 'sometimes|numeric|min:0|max:1000000',
|
||||
]);
|
||||
|
||||
if ($request->credits) {
|
||||
if ($user->credits + $request->credits >= 99999999) throw ValidationException::withMessages([
|
||||
'credits' => "You can't add this amount of credits because you would exceed the credit limit"
|
||||
]);
|
||||
if ($user->credits + $request->credits >= 99999999) {
|
||||
throw ValidationException::withMessages([
|
||||
'credits' => "You can't add this amount of credits because you would exceed the credit limit",
|
||||
]);
|
||||
}
|
||||
event(new UserUpdateCreditsEvent($user));
|
||||
$user->increment('credits', $request->credits);
|
||||
}
|
||||
|
||||
if ($request->server_limit) {
|
||||
if ($user->server_limit + $request->server_limit >= 2147483647) throw ValidationException::withMessages([
|
||||
'server_limit' => "You cannot add this amount of servers because it would exceed the server limit."
|
||||
]);
|
||||
if ($user->server_limit + $request->server_limit >= 2147483647) {
|
||||
throw ValidationException::withMessages([
|
||||
'server_limit' => 'You cannot add this amount of servers because it would exceed the server limit.',
|
||||
]);
|
||||
}
|
||||
$user->increment('server_limit', $request->server_limit);
|
||||
}
|
||||
|
||||
|
@ -152,9 +157,10 @@ class UserController extends Controller
|
|||
/**
|
||||
* decrements the users credits or/and server_limit
|
||||
*
|
||||
* @param Request $request
|
||||
* @param int $id
|
||||
* @param Request $request
|
||||
* @param int $id
|
||||
* @return User
|
||||
*
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function decrement(Request $request, int $id)
|
||||
|
@ -163,21 +169,25 @@ class UserController extends Controller
|
|||
$user = $discordUser ? $discordUser->user : User::findOrFail($id);
|
||||
|
||||
$request->validate([
|
||||
"credits" => "sometimes|numeric|min:0|max:1000000",
|
||||
"server_limit" => "sometimes|numeric|min:0|max:1000000",
|
||||
'credits' => 'sometimes|numeric|min:0|max:1000000',
|
||||
'server_limit' => 'sometimes|numeric|min:0|max:1000000',
|
||||
]);
|
||||
|
||||
if ($request->credits) {
|
||||
if ($user->credits - $request->credits < 0) throw ValidationException::withMessages([
|
||||
'credits' => "You can't remove this amount of credits because you would exceed the minimum credit limit"
|
||||
]);
|
||||
if ($user->credits - $request->credits < 0) {
|
||||
throw ValidationException::withMessages([
|
||||
'credits' => "You can't remove this amount of credits because you would exceed the minimum credit limit",
|
||||
]);
|
||||
}
|
||||
$user->decrement('credits', $request->credits);
|
||||
}
|
||||
|
||||
if ($request->server_limit) {
|
||||
if ($user->server_limit - $request->server_limit < 0) throw ValidationException::withMessages([
|
||||
'server_limit' => "You cannot remove this amount of servers because it would exceed the minimum server."
|
||||
]);
|
||||
if ($user->server_limit - $request->server_limit < 0) {
|
||||
throw ValidationException::withMessages([
|
||||
'server_limit' => 'You cannot remove this amount of servers because it would exceed the minimum server.',
|
||||
]);
|
||||
}
|
||||
$user->decrement('server_limit', $request->server_limit);
|
||||
}
|
||||
|
||||
|
@ -187,9 +197,10 @@ class UserController extends Controller
|
|||
/**
|
||||
* Suspends the user
|
||||
*
|
||||
* @param Request $request
|
||||
* @param int $id
|
||||
* @param Request $request
|
||||
* @param int $id
|
||||
* @return bool
|
||||
*
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function suspend(Request $request, int $id)
|
||||
|
@ -210,9 +221,10 @@ class UserController extends Controller
|
|||
/**
|
||||
* Unsuspend the user
|
||||
*
|
||||
* @param Request $request
|
||||
* @param int $id
|
||||
* @param Request $request
|
||||
* @param int $id
|
||||
* @return bool
|
||||
*
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function unsuspend(Request $request, int $id)
|
||||
|
@ -222,7 +234,7 @@ class UserController extends Controller
|
|||
|
||||
if (!$user->isSuspended()) {
|
||||
throw ValidationException::withMessages([
|
||||
'error' => "You cannot unsuspend an User who is not suspended."
|
||||
'error' => 'You cannot unsuspend an User who is not suspended.',
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -230,17 +242,7 @@ class UserController extends Controller
|
|||
|
||||
return $user;
|
||||
}
|
||||
/**
|
||||
* Create a unique Referral Code for User
|
||||
* @return string
|
||||
*/
|
||||
protected function createReferralCode(){
|
||||
$referralcode = STR::random(8);
|
||||
if (User::where('referral_code', '=', $referralcode)->exists()) {
|
||||
$this->createReferralCode();
|
||||
}
|
||||
return $referralcode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
|
@ -251,13 +253,13 @@ class UserController extends Controller
|
|||
'email' => ['required', 'string', 'email', 'max:64', 'unique:users'],
|
||||
'password' => ['required', 'string', 'min:8', 'max:191'],
|
||||
]);
|
||||
|
||||
|
||||
// Prevent the creation of new users via API if this is enabled.
|
||||
if (!config('SETTINGS::SYSTEM:CREATION_OF_NEW_USERS', 'true')) {
|
||||
throw ValidationException::withMessages([
|
||||
'error' => "The creation of new users has been blocked by the system administrator."
|
||||
'error' => 'The creation of new users has been blocked by the system administrator.',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$user = User::create([
|
||||
'name' => $request->input('name'),
|
||||
|
@ -269,45 +271,44 @@ class UserController extends Controller
|
|||
]);
|
||||
|
||||
$response = Pterodactyl::client()->post('/application/users', [
|
||||
"external_id" => App::environment('local') ? Str::random(16) : (string)$user->id,
|
||||
"username" => $user->name,
|
||||
"email" => $user->email,
|
||||
"first_name" => $user->name,
|
||||
"last_name" => $user->name,
|
||||
"password" => $request->input('password'),
|
||||
"root_admin" => false,
|
||||
"language" => "en"
|
||||
'external_id' => App::environment('local') ? Str::random(16) : (string) $user->id,
|
||||
'username' => $user->name,
|
||||
'email' => $user->email,
|
||||
'first_name' => $user->name,
|
||||
'last_name' => $user->name,
|
||||
'password' => $request->input('password'),
|
||||
'root_admin' => false,
|
||||
'language' => 'en',
|
||||
]);
|
||||
|
||||
if ($response->failed()) {
|
||||
$user->delete();
|
||||
throw ValidationException::withMessages([
|
||||
'pterodactyl_error_message' => $response->toException()->getMessage(),
|
||||
'pterodactyl_error_status' => $response->toException()->getCode()
|
||||
'pterodactyl_error_status' => $response->toException()->getCode(),
|
||||
]);
|
||||
}
|
||||
|
||||
$user->update([
|
||||
'pterodactyl_id' => $response->json()['attributes']['id']
|
||||
'pterodactyl_id' => $response->json()['attributes']['id'],
|
||||
]);
|
||||
//INCREMENT REFERRAL-USER CREDITS
|
||||
if(!empty($request->input("referral_code"))){
|
||||
$ref_code = $request->input("referral_code");
|
||||
if (!empty($request->input('referral_code'))) {
|
||||
$ref_code = $request->input('referral_code');
|
||||
$new_user = $user->id;
|
||||
if($ref_user = User::query()->where('referral_code', '=', $ref_code)->first()) {
|
||||
if(config("SETTINGS::REFERRAL:MODE") == "register" || config("SETTINGS::REFERRAL:MODE") == "both") {
|
||||
$ref_user->increment('credits', config("SETTINGS::REFERRAL::REWARD"));
|
||||
if ($ref_user = User::query()->where('referral_code', '=', $ref_code)->first()) {
|
||||
if (config('SETTINGS::REFERRAL:MODE') == 'register' || config('SETTINGS::REFERRAL:MODE') == 'both') {
|
||||
$ref_user->increment('credits', config('SETTINGS::REFERRAL::REWARD'));
|
||||
$ref_user->notify(new ReferralNotification($ref_user->id, $new_user));
|
||||
}
|
||||
//INSERT INTO USER_REFERRALS TABLE
|
||||
DB::table('user_referrals')->insert([
|
||||
'referral_id' => $ref_user->id,
|
||||
'registered_user_id' => $user->id,
|
||||
'created_at' => Carbon::now(),
|
||||
'updated_at' => Carbon::now()
|
||||
'created_at' => Carbon::now(),
|
||||
'updated_at' => Carbon::now(),
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
$user->sendEmailVerificationNotification();
|
||||
|
||||
|
@ -317,7 +318,7 @@ class UserController extends Controller
|
|||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param int $id
|
||||
* @param int $id
|
||||
* @return Application|Response|ResponseFactory
|
||||
*/
|
||||
public function destroy(int $id)
|
||||
|
@ -326,6 +327,7 @@ class UserController extends Controller
|
|||
$user = $discordUser ? $discordUser->user : User::findOrFail($id);
|
||||
|
||||
$user->delete();
|
||||
|
||||
return response($user, 200);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ use Spatie\QueryBuilder\QueryBuilder;
|
|||
class VoucherController extends Controller
|
||||
{
|
||||
const ALLOWED_INCLUDES = ['users'];
|
||||
|
||||
const ALLOWED_FILTERS = ['code', 'memo', 'credits', 'uses'];
|
||||
|
||||
/**
|
||||
|
@ -44,7 +45,7 @@ class VoucherController extends Controller
|
|||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
|
@ -54,7 +55,7 @@ class VoucherController extends Controller
|
|||
'code' => 'required|string|alpha_dash|max:36|min:4|unique:vouchers',
|
||||
'uses' => 'required|numeric|max:2147483647|min:1',
|
||||
'credits' => 'required|numeric|between:0,99999999',
|
||||
'expires_at' => 'nullable|multiple_date_format:d-m-Y H:i:s,d-m-Y|after:now|before:10 years'
|
||||
'expires_at' => 'nullable|multiple_date_format:d-m-Y H:i:s,d-m-Y|after:now|before:10 years',
|
||||
]);
|
||||
|
||||
return Voucher::create($request->all());
|
||||
|
@ -63,8 +64,7 @@ class VoucherController extends Controller
|
|||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @param int $id
|
||||
* @return Voucher|Collection|Model
|
||||
*/
|
||||
public function show(int $id)
|
||||
|
@ -79,7 +79,7 @@ class VoucherController extends Controller
|
|||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @param int $id
|
||||
* @return Response
|
||||
*/
|
||||
public function edit($id)
|
||||
|
@ -90,8 +90,8 @@ class VoucherController extends Controller
|
|||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param int $id
|
||||
* @param Request $request
|
||||
* @param int $id
|
||||
* @return Response
|
||||
*/
|
||||
public function update(Request $request, int $id)
|
||||
|
@ -103,7 +103,7 @@ class VoucherController extends Controller
|
|||
'code' => "required|string|alpha_dash|max:36|min:4|unique:vouchers,code,{$voucher->id}",
|
||||
'uses' => 'required|numeric|max:2147483647|min:1',
|
||||
'credits' => 'required|numeric|between:0,99999999',
|
||||
'expires_at' => 'nullable|multiple_date_format:d-m-Y H:i:s,d-m-Y|after:now|before:10 years'
|
||||
'expires_at' => 'nullable|multiple_date_format:d-m-Y H:i:s,d-m-Y|after:now|before:10 years',
|
||||
]);
|
||||
|
||||
$voucher->update($request->all());
|
||||
|
@ -114,21 +114,22 @@ class VoucherController extends Controller
|
|||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param int $id
|
||||
* @param int $id
|
||||
* @return Response
|
||||
*/
|
||||
public function destroy(int $id)
|
||||
{
|
||||
$voucher = Voucher::findOrFail($id);
|
||||
$voucher->delete();
|
||||
|
||||
return $voucher;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get linked users
|
||||
* @param Request $request
|
||||
* @param Voucher $voucher
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Voucher $voucher
|
||||
* @return LengthAwarePaginator
|
||||
*/
|
||||
public function users(Request $request, Voucher $voucher)
|
||||
|
@ -138,7 +139,7 @@ class VoucherController extends Controller
|
|||
'nullable',
|
||||
'string',
|
||||
Rule::in(['discorduser']),
|
||||
]
|
||||
],
|
||||
]);
|
||||
|
||||
if ($request->input('include') == 'discorduser') {
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace App\Http\Controllers\Auth;
|
|||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ForgotPasswordController extends Controller
|
||||
{
|
||||
|
@ -19,4 +20,27 @@ class ForgotPasswordController extends Controller
|
|||
*/
|
||||
|
||||
use SendsPasswordResetEmails;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('guest');
|
||||
}
|
||||
|
||||
protected function validateEmail(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'email' => ['required', 'string', 'email', 'max:255'],
|
||||
]);
|
||||
|
||||
if (config('SETTINGS::RECAPTCHA:ENABLED') == 'true') {
|
||||
$this->validate($request, [
|
||||
'g-recaptcha-response' => 'required|recaptcha',
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,12 +3,10 @@
|
|||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\User;
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class LoginController extends Controller
|
||||
{
|
||||
|
@ -42,20 +40,30 @@ class LoginController extends Controller
|
|||
$this->middleware('guest')->except('logout');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the login username to be used by the controller.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function username()
|
||||
{
|
||||
$login = request()->input('email');
|
||||
$field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'name';
|
||||
request()->merge([$field => $login]);
|
||||
return $field;
|
||||
}
|
||||
|
||||
public function login(Request $request)
|
||||
{
|
||||
|
||||
$validationRules = [
|
||||
$this->username() => 'required|string',
|
||||
'password' => 'required|string',
|
||||
$this->username() => 'required|string',
|
||||
'password' => 'required|string',
|
||||
];
|
||||
if (config('SETTINGS::RECAPTCHA:ENABLED') == 'true') {
|
||||
$validationRules['g-recaptcha-response'] = ['required', 'recaptcha'];
|
||||
}
|
||||
$request->validate($validationRules);
|
||||
|
||||
|
||||
|
||||
// If the class is using the ThrottlesLogins trait, we can automatically throttle
|
||||
// the login attempts for this application. We'll key this by the username and
|
||||
// the IP address of the client making these requests into this application.
|
||||
|
@ -72,6 +80,7 @@ class LoginController extends Controller
|
|||
$user = Auth::user();
|
||||
$user->last_seen = now();
|
||||
$user->save();
|
||||
|
||||
return $this->sendLoginResponse($request);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,14 +4,13 @@ namespace App\Http\Controllers\Auth;
|
|||
|
||||
use App\Classes\Pterodactyl;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Settings;
|
||||
use App\Models\User;
|
||||
use App\Notifications\ReferralNotification;
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use App\Traits\Referral;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Foundation\Auth\RegistersUsers;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
@ -32,7 +31,7 @@ class RegisterController extends Controller
|
|||
|
|
||||
*/
|
||||
|
||||
use RegistersUsers;
|
||||
use RegistersUsers, Referral;
|
||||
|
||||
/**
|
||||
* Where to redirect users after registration.
|
||||
|
@ -54,28 +53,34 @@ class RegisterController extends Controller
|
|||
/**
|
||||
* Get a validator for an incoming registration request.
|
||||
*
|
||||
* @param array $data
|
||||
* @param array $data
|
||||
* @return \Illuminate\Contracts\Validation\Validator
|
||||
*/
|
||||
protected function validator(array $data)
|
||||
{
|
||||
$validationRules = [
|
||||
'name' => ['required', 'string', 'max:30', 'min:4', 'alpha_num', 'unique:users'],
|
||||
'email' => ['required', 'string', 'email', 'max:64', 'unique:users'],
|
||||
'password' => ['required', 'string', 'min:8', 'confirmed'],
|
||||
'name' => ['required', 'string', 'max:30', 'min:4', 'alpha_num', 'unique:users'],
|
||||
'email' => ['required', 'string', 'email', 'max:64', 'unique:users'],
|
||||
'password' => ['required', 'string', 'min:8', 'confirmed'],
|
||||
];
|
||||
if (config('SETTINGS::RECAPTCHA:ENABLED') == 'true') {
|
||||
$validationRules['g-recaptcha-response'] = ['required', 'recaptcha'];
|
||||
}
|
||||
if (config('SETTINGS::SYSTEM:SHOW_TOS') == 'true') {
|
||||
$validationRules['terms'] = ['required'];
|
||||
}
|
||||
|
||||
if (config('SETTINGS::SYSTEM:REGISTER_IP_CHECK', 'true') == 'true') {
|
||||
|
||||
//check if ip has already made an account
|
||||
$data['ip'] = session()->get('ip') ?? request()->ip();
|
||||
if (User::where('ip', '=', request()->ip())->exists()) session()->put('ip', request()->ip());
|
||||
$validationRules['ip'] = ['unique:users'];
|
||||
if (User::where('ip', '=', request()->ip())->exists()) {
|
||||
session()->put('ip', request()->ip());
|
||||
}
|
||||
$validationRules['ip'] = ['unique:users'];
|
||||
|
||||
return Validator::make($data, $validationRules, [
|
||||
'ip.unique' => "You have already made an account! Please contact support if you think this is incorrect."
|
||||
'ip.unique' => 'You have already made an account! Please contact support if you think this is incorrect.',
|
||||
|
||||
]);
|
||||
}
|
||||
|
@ -83,82 +88,70 @@ class RegisterController extends Controller
|
|||
return Validator::make($data, $validationRules);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a unique Referral Code for User
|
||||
* @return string
|
||||
*/
|
||||
protected function createReferralCode(){
|
||||
$referralcode = STR::random(8);
|
||||
if (User::where('referral_code', '=', $referralcode)->exists()) {
|
||||
$this->createReferralCode();
|
||||
}
|
||||
return $referralcode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new user instance after a valid registration.
|
||||
*
|
||||
* @param array $data
|
||||
* @param array $data
|
||||
* @return User
|
||||
*/
|
||||
protected function create(array $data)
|
||||
{
|
||||
$user = User::create([
|
||||
'name' => $data['name'],
|
||||
'email' => $data['email'],
|
||||
'credits' => config('SETTINGS::USER:INITIAL_CREDITS', 150),
|
||||
'name' => $data['name'],
|
||||
'email' => $data['email'],
|
||||
'credits' => config('SETTINGS::USER:INITIAL_CREDITS', 150),
|
||||
'server_limit' => config('SETTINGS::USER:INITIAL_SERVER_LIMIT', 1),
|
||||
'password' => Hash::make($data['password']),
|
||||
'password' => Hash::make($data['password']),
|
||||
'referral_code' => $this->createReferralCode(),
|
||||
|
||||
]);
|
||||
|
||||
$response = Pterodactyl::client()->post('/application/users', [
|
||||
"external_id" => App::environment('local') ? Str::random(16) : (string)$user->id,
|
||||
"username" => $user->name,
|
||||
"email" => $user->email,
|
||||
"first_name" => $user->name,
|
||||
"last_name" => $user->name,
|
||||
"password" => $data['password'],
|
||||
"root_admin" => false,
|
||||
"language" => "en"
|
||||
'external_id' => App::environment('local') ? Str::random(16) : (string) $user->id,
|
||||
'username' => $user->name,
|
||||
'email' => $user->email,
|
||||
'first_name' => $user->name,
|
||||
'last_name' => $user->name,
|
||||
'password' => $data['password'],
|
||||
'root_admin' => false,
|
||||
'language' => 'en',
|
||||
]);
|
||||
|
||||
if ($response->failed()) {
|
||||
$user->delete();
|
||||
Log::error('Pterodactyl Registration Error: ' . $response->json()['errors'][0]['detail']);
|
||||
throw ValidationException::withMessages([
|
||||
'ptero_registration_error' => [__('Account already exists on Pterodactyl. Please contact the Support!')],
|
||||
]);
|
||||
}
|
||||
|
||||
$user->update([
|
||||
'pterodactyl_id' => $response->json()['attributes']['id']
|
||||
'pterodactyl_id' => $response->json()['attributes']['id'],
|
||||
]);
|
||||
|
||||
//INCREMENT REFERRAL-USER CREDITS
|
||||
if(!empty($data['referral_code'])){
|
||||
if (!empty($data['referral_code'])) {
|
||||
$ref_code = $data['referral_code'];
|
||||
$new_user = $user->id;
|
||||
if($ref_user = User::query()->where('referral_code', '=', $ref_code)->first()) {
|
||||
if(config("SETTINGS::REFERRAL:MODE") == "sign-up" || config("SETTINGS::REFERRAL:MODE") == "both") {
|
||||
$ref_user->increment('credits', config("SETTINGS::REFERRAL::REWARD"));
|
||||
if ($ref_user = User::query()->where('referral_code', '=', $ref_code)->first()) {
|
||||
if (config('SETTINGS::REFERRAL:MODE') == 'sign-up' || config('SETTINGS::REFERRAL:MODE') == 'both') {
|
||||
$ref_user->increment('credits', config('SETTINGS::REFERRAL::REWARD'));
|
||||
$ref_user->notify(new ReferralNotification($ref_user->id, $new_user));
|
||||
|
||||
//LOGS REFERRALS IN THE ACTIVITY LOG
|
||||
activity()
|
||||
->performedOn($user)
|
||||
->causedBy($ref_user)
|
||||
->log('gained '. config("SETTINGS::REFERRAL::REWARD").' '.config("SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME").' for sign-up-referral of '.$user->name.' (ID:'.$user->id.')');
|
||||
->log('gained ' . config('SETTINGS::REFERRAL::REWARD') . ' ' . config('SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME') . ' for sign-up-referral of ' . $user->name . ' (ID:' . $user->id . ')');
|
||||
}
|
||||
//INSERT INTO USER_REFERRALS TABLE
|
||||
DB::table('user_referrals')->insert([
|
||||
'referral_id' => $ref_user->id,
|
||||
'registered_user_id' => $user->id,
|
||||
'created_at' => Carbon::now(),
|
||||
'updated_at' => Carbon::now()
|
||||
'created_at' => Carbon::now(),
|
||||
'updated_at' => Carbon::now(),
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $user;
|
||||
|
|
|
@ -4,10 +4,7 @@ namespace App\Http\Controllers\Auth;
|
|||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\DiscordUser;
|
||||
use App\Models\Settings;
|
||||
use App\Models\User;
|
||||
use App\Models\Voucher;
|
||||
use Exception;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Laravel\Socialite\Facades\Socialite;
|
||||
|
@ -16,7 +13,7 @@ class SocialiteController extends Controller
|
|||
{
|
||||
public function redirect()
|
||||
{
|
||||
$scopes = !empty(config("SETTINGS::DISCORD:BOT_TOKEN")) && !empty(config("SETTINGS::DISCORD:GUILD_ID")) ? ['guilds.join'] : [];
|
||||
$scopes = ! empty(config('SETTINGS::DISCORD:BOT_TOKEN')) && ! empty(config('SETTINGS::DISCORD:GUILD_ID')) ? ['guilds.join'] : [];
|
||||
|
||||
return Socialite::driver('discord')
|
||||
->scopes($scopes)
|
||||
|
@ -32,40 +29,39 @@ class SocialiteController extends Controller
|
|||
/** @var User $user */
|
||||
$user = Auth::user();
|
||||
$discord = Socialite::driver('discord')->user();
|
||||
$botToken = config("SETTINGS::DISCORD:BOT_TOKEN");
|
||||
$guildId = config("SETTINGS::DISCORD:GUILD_ID");
|
||||
$roleId = config("SETTINGS::DISCORD:ROLE_ID");
|
||||
$botToken = config('SETTINGS::DISCORD:BOT_TOKEN');
|
||||
$guildId = config('SETTINGS::DISCORD:GUILD_ID');
|
||||
$roleId = config('SETTINGS::DISCORD:ROLE_ID');
|
||||
|
||||
//save / update discord_users
|
||||
//save / update discord_users
|
||||
|
||||
//check if discord account is already linked to an cpgg account
|
||||
if (is_null($user->discordUser)) {
|
||||
$discordLinked = DiscordUser::where('id', '=', $discord->id)->first();
|
||||
if ($discordLinked !== null) {
|
||||
return redirect()->route('profile.index')->with(
|
||||
//check if discord account is already linked to an cpgg account
|
||||
if (is_null($user->discordUser)) {
|
||||
$discordLinked = DiscordUser::where('id', '=', $discord->id)->first();
|
||||
if ($discordLinked !== null) {
|
||||
return redirect()->route('profile.index')->with(
|
||||
'error',
|
||||
'Discord account already linked!'
|
||||
);
|
||||
}
|
||||
|
||||
//create discord user in db
|
||||
DiscordUser::create(array_merge($discord->user, ['user_id' => Auth::user()->id]));
|
||||
|
||||
//update user
|
||||
Auth::user()->increment('credits', config('SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_DISCORD'));
|
||||
Auth::user()->increment('server_limit', config('SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_DISCORD'));
|
||||
Auth::user()->update(['discord_verified_at' => now()]);
|
||||
|
||||
} else {
|
||||
$user->discordUser->update($discord->user);
|
||||
}
|
||||
|
||||
//create discord user in db
|
||||
DiscordUser::create(array_merge($discord->user, ['user_id' => Auth::user()->id]));
|
||||
|
||||
//update user
|
||||
Auth::user()->increment('credits', config('SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_DISCORD'));
|
||||
Auth::user()->increment('server_limit', config('SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_DISCORD'));
|
||||
Auth::user()->update(['discord_verified_at' => now()]);
|
||||
} else {
|
||||
$user->discordUser->update($discord->user);
|
||||
}
|
||||
|
||||
//force user into discord server
|
||||
//TODO Add event on failure, to notify ppl involved
|
||||
if (!empty($guildId) && !empty($botToken)) {
|
||||
if (! empty($guildId) && ! empty($botToken)) {
|
||||
$response = Http::withHeaders(
|
||||
[
|
||||
'Authorization' => 'Bot ' . $botToken,
|
||||
'Authorization' => 'Bot '.$botToken,
|
||||
'Content-Type' => 'application/json',
|
||||
]
|
||||
)->put(
|
||||
|
@ -74,10 +70,10 @@ class SocialiteController extends Controller
|
|||
);
|
||||
|
||||
//give user a role in the discord server
|
||||
if (!empty($roleId)) {
|
||||
if (! empty($roleId)) {
|
||||
$response = Http::withHeaders(
|
||||
[
|
||||
'Authorization' => 'Bot ' . $botToken,
|
||||
'Authorization' => 'Bot '.$botToken,
|
||||
'Content-Type' => 'application/json',
|
||||
]
|
||||
)->put(
|
||||
|
|
|
@ -2,39 +2,46 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\PartnerDiscount;
|
||||
use App\Models\UsefulLink;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
|
||||
|
||||
class HomeController extends Controller
|
||||
{
|
||||
const TIME_LEFT_BG_SUCCESS = "bg-success";
|
||||
const TIME_LEFT_BG_WARNING = "bg-warning";
|
||||
const TIME_LEFT_BG_DANGER = "bg-danger";
|
||||
const TIME_LEFT_BG_SUCCESS = 'bg-success';
|
||||
|
||||
const TIME_LEFT_BG_WARNING = 'bg-warning';
|
||||
|
||||
const TIME_LEFT_BG_DANGER = 'bg-danger';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
public function callHome(){
|
||||
if(Storage::exists("callHome")){return;}
|
||||
Http::asForm()->post('https://market.controlpanel.gg/callhome.php', [
|
||||
'id' => Hash::make(URL::current())
|
||||
/*
|
||||
* TODO: This is commented due to the fact the market is a bad dependency, will be changed later.
|
||||
public function callHome()
|
||||
{
|
||||
if (Storage::exists('callHome')) {
|
||||
return;
|
||||
}
|
||||
Http::asForm()->post('https://market.ctrlpanel.gg/callhome.php', [
|
||||
'id' => Hash::make(URL::current()),
|
||||
]);
|
||||
Storage::put('callHome', 'This is only used to count the installations of cpgg.');
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* @description Get the Background Color for the Days-Left-Box in HomeView
|
||||
*
|
||||
* @param float $daysLeft
|
||||
*
|
||||
* @param float $daysLeft
|
||||
* @return string
|
||||
*/
|
||||
public function getTimeLeftBoxBackground(float $daysLeft): string
|
||||
|
@ -45,36 +52,40 @@ class HomeController extends Controller
|
|||
if ($daysLeft <= 7) {
|
||||
return $this::TIME_LEFT_BG_DANGER;
|
||||
}
|
||||
|
||||
return $this::TIME_LEFT_BG_WARNING;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @description Set "hours", "days" or nothing behind the remaining time
|
||||
*
|
||||
* @param float $daysLeft
|
||||
* @param float $hoursLeft
|
||||
*
|
||||
* @param float $daysLeft
|
||||
* @param float $hoursLeft
|
||||
* @return string|void
|
||||
*/
|
||||
public function getTimeLeftBoxUnit(float $daysLeft, float $hoursLeft)
|
||||
{
|
||||
if ($daysLeft > 1) return __('days');
|
||||
return $hoursLeft < 1 ? null : __("hours");
|
||||
if ($daysLeft > 1) {
|
||||
return __('days');
|
||||
}
|
||||
|
||||
return $hoursLeft < 1 ? null : __('hours');
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Get the Text for the Days-Left-Box in HomeView
|
||||
*
|
||||
* @param float $daysLeft
|
||||
* @param float $hoursLeft
|
||||
*
|
||||
* @param float $daysLeft
|
||||
* @param float $hoursLeft
|
||||
* @return string
|
||||
*/
|
||||
public function getTimeLeftBoxText(float $daysLeft, float $hoursLeft)
|
||||
{
|
||||
if ($daysLeft > 1) return strval(number_format($daysLeft, 0));
|
||||
return ($hoursLeft < 1 ? __("You ran out of Credits") : strval($hoursLeft));
|
||||
if ($daysLeft > 1) {
|
||||
return strval(number_format($daysLeft, 0));
|
||||
}
|
||||
|
||||
return $hoursLeft < 1 ? __('You ran out of Credits') : strval($hoursLeft);
|
||||
}
|
||||
|
||||
/** Show the application dashboard. */
|
||||
|
@ -82,9 +93,9 @@ class HomeController extends Controller
|
|||
{
|
||||
$usage = Auth::user()->creditUsage();
|
||||
$credits = Auth::user()->Credits();
|
||||
$bg = "";
|
||||
$boxText = "";
|
||||
$unit = "";
|
||||
$bg = '';
|
||||
$boxText = '';
|
||||
$unit = '';
|
||||
|
||||
/** Build our Time-Left-Box */
|
||||
if ($credits > 0.01 and $usage > 0) {
|
||||
|
@ -93,19 +104,22 @@ class HomeController extends Controller
|
|||
|
||||
$bg = $this->getTimeLeftBoxBackground($daysLeft);
|
||||
$boxText = $this->getTimeLeftBoxText($daysLeft, $hoursLeft);
|
||||
$unit = $daysLeft < 1 ? ($hoursLeft < 1 ? null : __("hours")) : __("days");
|
||||
$unit = $daysLeft < 1 ? ($hoursLeft < 1 ? null : __('hours')) : __('days');
|
||||
}
|
||||
|
||||
$this->callhome();
|
||||
//$this->callhome(); TODO: Same as the function
|
||||
|
||||
// RETURN ALL VALUES
|
||||
return view('home')->with([
|
||||
'usage' => $usage,
|
||||
'credits' => $credits,
|
||||
'useful_links' => UsefulLink::all()->sortBy('id'),
|
||||
'useful_links_dashboard' => UsefulLink::where("position","like","%dashboard%")->get()->sortby("id"),
|
||||
'bg' => $bg,
|
||||
'boxText' => $boxText,
|
||||
'unit' => $unit
|
||||
'unit' => $unit,
|
||||
'numberOfReferrals' => DB::table('user_referrals')->where('referral_id', '=', Auth::user()->id)->count(),
|
||||
'partnerDiscount' => PartnerDiscount::where('user_id', Auth::user()->id)->first(),
|
||||
'myDiscount' => PartnerDiscount::getDiscount(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
117
app/Http/Controllers/Moderation/TicketCategoryController.php
Normal file
117
app/Http/Controllers/Moderation/TicketCategoryController.php
Normal file
|
@ -0,0 +1,117 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Moderation;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Ticket;
|
||||
use App\Models\TicketCategory;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class TicketCategoryController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$categories = TicketCategory::all();
|
||||
return view('moderator.ticket.category')->with("categories",$categories);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'name' => 'required|string|max:191',
|
||||
]);
|
||||
|
||||
TicketCategory::create($request->all());
|
||||
|
||||
|
||||
return redirect(route("moderator.ticket.category.index"))->with("success",__("Category created"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'category' => 'required|int',
|
||||
'name' => 'required|string|max:191',
|
||||
]);
|
||||
|
||||
$category = TicketCategory::where("id",$request->category)->firstOrFail();
|
||||
|
||||
$category->name = $request->name;
|
||||
$category->save();
|
||||
|
||||
return redirect()->back()->with("success",__("Category name updated"));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
$category = TicketCategory::where("id",$id)->firstOrFail();
|
||||
|
||||
if($category->id == 5 ){ //cannot delete "other" category
|
||||
return back()->with("error","You cannot delete that category");
|
||||
}
|
||||
|
||||
$tickets = Ticket::where("ticketcategory_id",$category->id)->get();
|
||||
|
||||
foreach($tickets as $ticket){
|
||||
$ticket->ticketcategory_id = "5";
|
||||
$ticket->save();
|
||||
}
|
||||
|
||||
$category->delete();
|
||||
|
||||
return redirect()
|
||||
->route('moderator.ticket.category.index')
|
||||
->with('success', __('Category removed'));
|
||||
}
|
||||
|
||||
public function datatable()
|
||||
{
|
||||
$query = TicketCategory::withCount("tickets");
|
||||
|
||||
return datatables($query)
|
||||
->addColumn('name', function ( TicketCategory $category) {
|
||||
return $category->name;
|
||||
})
|
||||
->editColumn('tickets', function ( TicketCategory $category) {
|
||||
return $category->tickets_count;
|
||||
})
|
||||
->addColumn('actions', function (TicketCategory $category) {
|
||||
return '
|
||||
<form class="d-inline" onsubmit="return submitResult();" method="post" action="'.route('moderator.ticket.category.destroy', $category->id).'">
|
||||
'.csrf_field().'
|
||||
'.method_field('DELETE').'
|
||||
<button data-content="'.__('Delete').'" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm btn-danger mr-1"><i class="fas fa-trash"></i></button>
|
||||
</form>
|
||||
';
|
||||
})
|
||||
->editColumn('created_at', function (TicketCategory $category) {
|
||||
return $category->created_at ? $category->created_at->diffForHumans() : '';
|
||||
})
|
||||
->rawColumns(['actions'])
|
||||
->make();
|
||||
}
|
||||
}
|
|
@ -2,63 +2,102 @@
|
|||
|
||||
namespace App\Http\Controllers\Moderation;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Models\Ticket;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Server;
|
||||
use App\Models\Ticket;
|
||||
use App\Models\TicketBlacklist;
|
||||
use App\Models\TicketCategory;
|
||||
use App\Models\TicketComment;
|
||||
use App\Models\TicketBlacklist;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use App\Models\User;
|
||||
use App\Notifications\Ticket\User\ReplyNotification;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use App\Notifications\Ticket\User\ReplyNotification;
|
||||
|
||||
class TicketsController extends Controller
|
||||
{
|
||||
public function index() {
|
||||
$tickets = Ticket::orderBy('id','desc')->paginate(10);
|
||||
public function index()
|
||||
{
|
||||
$tickets = Ticket::orderBy('id', 'desc')->paginate(10);
|
||||
$ticketcategories = TicketCategory::all();
|
||||
return view("moderator.ticket.index", compact("tickets", "ticketcategories"));
|
||||
|
||||
return view('moderator.ticket.index', compact('tickets', 'ticketcategories'));
|
||||
}
|
||||
public function show($ticket_id) {
|
||||
$ticket = Ticket::where("ticket_id", $ticket_id)->firstOrFail();
|
||||
|
||||
public function show($ticket_id)
|
||||
{
|
||||
try {
|
||||
$ticket = Ticket::where('ticket_id', $ticket_id)->firstOrFail();
|
||||
} catch (Exception $e)
|
||||
{
|
||||
return redirect()->back()->with('warning', __('Ticket not found on the server. It potentially got deleted earlier'));
|
||||
}
|
||||
$ticketcomments = $ticket->ticketcomments;
|
||||
$ticketcategory = $ticket->ticketcategory;
|
||||
$server = Server::where('id', $ticket->server)->first();
|
||||
return view("moderator.ticket.show", compact("ticket", "ticketcategory", "ticketcomments", "server"));
|
||||
|
||||
return view('moderator.ticket.show', compact('ticket', 'ticketcategory', 'ticketcomments', 'server'));
|
||||
}
|
||||
|
||||
public function close($ticket_id) {
|
||||
$ticket = Ticket::where("ticket_id", $ticket_id)->firstOrFail();
|
||||
$ticket->status = "Closed";
|
||||
public function changeStatus($ticket_id)
|
||||
{
|
||||
try {
|
||||
$ticket = Ticket::where('ticket_id', $ticket_id)->firstOrFail();
|
||||
} catch(Exception $e)
|
||||
{
|
||||
return redirect()->back()->with('warning', __('Ticket not found on the server. It potentially got deleted earlier'));
|
||||
}
|
||||
|
||||
if($ticket->status == "Closed"){
|
||||
$ticket->status = "Reopened";
|
||||
$ticket->save();
|
||||
return redirect()->back()->with('success', __('A ticket has been reopened, ID: #') . $ticket->ticket_id);
|
||||
}
|
||||
$ticket->status = 'Closed';
|
||||
$ticket->save();
|
||||
$ticketOwner = $ticket->user;
|
||||
return redirect()->back()->with('success', __('A ticket has been closed, ID: #') . $ticket->ticket_id);
|
||||
|
||||
return redirect()->back()->with('success', __('A ticket has been closed, ID: #').$ticket->ticket_id);
|
||||
}
|
||||
|
||||
public function delete($ticket_id){
|
||||
$ticket = Ticket::where("ticket_id", $ticket_id)->firstOrFail();
|
||||
TicketComment::where("ticket_id", $ticket->id)->delete();
|
||||
public function delete($ticket_id)
|
||||
{
|
||||
try {
|
||||
$ticket = Ticket::where('ticket_id', $ticket_id)->firstOrFail();
|
||||
} catch (Exception $e)
|
||||
{
|
||||
return redirect()->back()->with('warning', __('Ticket not found on the server. It potentially got deleted earlier'));
|
||||
}
|
||||
|
||||
TicketComment::where('ticket_id', $ticket->id)->delete();
|
||||
$ticket->delete();
|
||||
return redirect()->back()->with('success', __('A ticket has been deleted, ID: #') . $ticket_id);
|
||||
|
||||
return redirect()->back()->with('success', __('A ticket has been deleted, ID: #').$ticket_id);
|
||||
}
|
||||
|
||||
public function reply(Request $request) {
|
||||
$this->validate($request, array("ticketcomment" => "required"));
|
||||
$ticket = Ticket::where('id', $request->input("ticket_id"))->firstOrFail();
|
||||
$ticket->status = "Answered";
|
||||
public function reply(Request $request)
|
||||
{
|
||||
$this->validate($request, ['ticketcomment' => 'required']);
|
||||
try {
|
||||
$ticket = Ticket::where('id', $request->input('ticket_id'))->firstOrFail();
|
||||
} catch (Exception $e){
|
||||
return redirect()->back()->with('warning', __('Ticket not found on the server. It potentially got deleted earlier'));
|
||||
}
|
||||
$ticket->status = 'Answered';
|
||||
$ticket->update();
|
||||
TicketComment::create(array(
|
||||
"ticket_id" => $request->input("ticket_id"),
|
||||
"user_id" => Auth::user()->id,
|
||||
"ticketcomment" => $request->input("ticketcomment"),
|
||||
));
|
||||
TicketComment::create([
|
||||
'ticket_id' => $request->input('ticket_id'),
|
||||
'user_id' => Auth::user()->id,
|
||||
'ticketcomment' => $request->input('ticketcomment'),
|
||||
]);
|
||||
try {
|
||||
$user = User::where('id', $ticket->user_id)->firstOrFail();
|
||||
$newmessage = $request->input("ticketcomment");
|
||||
} catch(Exception $e)
|
||||
{
|
||||
return redirect()->back()->with('warning', __('User not found on the server. Check on the admin database or try again later.'));
|
||||
}
|
||||
$newmessage = $request->input('ticketcomment');
|
||||
$user->notify(new ReplyNotification($ticket, $user, $newmessage));
|
||||
|
||||
return redirect()->back()->with('success', __('Your comment has been submitted'));
|
||||
}
|
||||
|
||||
|
@ -71,28 +110,33 @@ class TicketsController extends Controller
|
|||
return $tickets->ticketcategory->name;
|
||||
})
|
||||
->editColumn('title', function (Ticket $tickets) {
|
||||
return '<a class="text-info" href="' . route('moderator.ticket.show', ['ticket_id' => $tickets->ticket_id]) . '">' . "#" . $tickets->ticket_id . " - " . $tickets->title . '</a>';
|
||||
return '<a class="text-info" href="'.route('moderator.ticket.show', ['ticket_id' => $tickets->ticket_id]).'">'.'#'.$tickets->ticket_id.' - '.htmlspecialchars($tickets->title).'</a>';
|
||||
})
|
||||
->editColumn('user_id', function (Ticket $tickets) {
|
||||
return '<a href="' . route('admin.users.show', $tickets->user->id) . '">' . $tickets->user->name . '</a>';
|
||||
return '<a href="'.route('admin.users.show', $tickets->user->id).'">'.$tickets->user->name.'</a>';
|
||||
})
|
||||
->addColumn('actions', function (Ticket $tickets) {
|
||||
$statusButtonColor = ($tickets->status == "Closed") ? 'btn-success' : 'btn-warning';
|
||||
$statusButtonIcon = ($tickets->status == "Closed") ? 'fa-redo' : 'fa-times';
|
||||
$statusButtonText = ($tickets->status == "Closed") ? __('Reopen') : __('Close');
|
||||
|
||||
return '
|
||||
<a data-content="'.__("View").'" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('moderator.ticket.show', ['ticket_id' => $tickets->ticket_id]) . '" class="btn btn-sm text-white btn-info mr-1"><i class="fas fa-eye"></i></a>
|
||||
<form class="d-inline" method="post" action="' . route('moderator.ticket.close', ['ticket_id' => $tickets->ticket_id ]) . '">
|
||||
' . csrf_field() . '
|
||||
' . method_field("POST") . '
|
||||
<button data-content="'.__("Close").'" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm text-white btn-warning mr-1"><i class="fas fa-times"></i></button>
|
||||
<a data-content="'.__('View').'" data-toggle="popover" data-trigger="hover" data-placement="top" href="'.route('moderator.ticket.show', ['ticket_id' => $tickets->ticket_id]).'" class="btn btn-sm text-white btn-info mr-1"><i class="fas fa-eye"></i></a>
|
||||
<form class="d-inline" method="post" action="'.route('moderator.ticket.changeStatus', ['ticket_id' => $tickets->ticket_id]).'">
|
||||
'.csrf_field().'
|
||||
'.method_field('POST').'
|
||||
<button data-content="'.__($statusButtonText).'" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm text-white '.$statusButtonColor.' mr-1"><i class="fas '.$statusButtonIcon.'"></i></button>
|
||||
</form>
|
||||
<form class="d-inline" method="post" action="' . route('moderator.ticket.delete', ['ticket_id' => $tickets->ticket_id ]) . '">
|
||||
' . csrf_field() . '
|
||||
' . method_field("POST") . '
|
||||
<button data-content="'.__("Delete").'" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm text-white btn-danger mr-1"><i class="fas fa-trash"></i></button>
|
||||
<form class="d-inline" method="post" action="'.route('moderator.ticket.delete', ['ticket_id' => $tickets->ticket_id]).'">
|
||||
'.csrf_field().'
|
||||
'.method_field('POST').'
|
||||
<button data-content="'.__('Delete').'" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm text-white btn-danger mr-1"><i class="fas fa-trash"></i></button>
|
||||
</form>
|
||||
';
|
||||
})
|
||||
->editColumn('status', function (Ticket $tickets) {
|
||||
switch ($tickets->status) {
|
||||
case 'Reopened':
|
||||
case 'Open':
|
||||
$badgeColor = 'badge-success';
|
||||
break;
|
||||
|
@ -107,93 +151,112 @@ class TicketsController extends Controller
|
|||
break;
|
||||
}
|
||||
|
||||
return '<span class="badge ' . $badgeColor . '">' . $tickets->status . '</span>';
|
||||
return '<span class="badge '.$badgeColor.'">'.$tickets->status.'</span>';
|
||||
})
|
||||
->editColumn('priority', function (Ticket $tickets) {
|
||||
return __($tickets->priority);
|
||||
})
|
||||
->editColumn('updated_at', function (Ticket $tickets) {
|
||||
return $tickets->updated_at ? $tickets->updated_at->diffForHumans() : '';
|
||||
return ['display' => $tickets->updated_at ? $tickets->updated_at->diffForHumans() : '',
|
||||
'raw' => $tickets->updated_at ? strtotime($tickets->updated_at) : ''];
|
||||
})
|
||||
->rawColumns(['category', 'title', 'user_id', 'status', 'updated_at', 'actions'])
|
||||
->rawColumns(['category', 'title', 'user_id', 'status', 'priority', 'updated_at', 'actions'])
|
||||
->make(true);
|
||||
}
|
||||
|
||||
public function blacklist() {
|
||||
return view("moderator.ticket.blacklist");
|
||||
public function blacklist()
|
||||
{
|
||||
return view('moderator.ticket.blacklist');
|
||||
}
|
||||
|
||||
public function blacklistAdd(Request $request) {
|
||||
$user = User::where('id', $request->user_id)->first();
|
||||
public function blacklistAdd(Request $request)
|
||||
{
|
||||
try {
|
||||
$user = User::where('id', $request->user_id)->firstOrFail();
|
||||
$check = TicketBlacklist::where('user_id', $user->id)->first();
|
||||
if($check){
|
||||
}
|
||||
catch (Exception $e){
|
||||
return redirect()->back()->with('warning', __('User not found on the server. Check the admin database or try again later.'));
|
||||
}
|
||||
if ($check) {
|
||||
$check->reason = $request->reason;
|
||||
$check->status = "True";
|
||||
$check->status = 'True';
|
||||
$check->save();
|
||||
|
||||
return redirect()->back()->with('info', __('Target User already in blacklist. Reason updated'));
|
||||
}
|
||||
TicketBlacklist::create(array(
|
||||
"user_id" => $user->id,
|
||||
"status" => "True",
|
||||
"reason" => $request->reason,
|
||||
));
|
||||
return redirect()->back()->with('success', __('Successfully add User to blacklist, User name: ' . $user->name));
|
||||
TicketBlacklist::create([
|
||||
'user_id' => $user->id,
|
||||
'status' => 'True',
|
||||
'reason' => $request->reason,
|
||||
]);
|
||||
|
||||
return redirect()->back()->with('success', __('Successfully add User to blacklist, User name: '.$user->name));
|
||||
}
|
||||
|
||||
|
||||
public function blacklistDelete($id) {
|
||||
public function blacklistDelete($id)
|
||||
{
|
||||
$blacklist = TicketBlacklist::where('id', $id)->first();
|
||||
$blacklist->delete();
|
||||
return redirect()->back()->with('success', __('Successfully remove User from blacklist, User name: ' . $blacklist->user->name));
|
||||
|
||||
return redirect()->back()->with('success', __('Successfully remove User from blacklist, User name: '.$blacklist->user->name));
|
||||
}
|
||||
|
||||
public function blacklistChange($id) {
|
||||
$blacklist = TicketBlacklist::where('id', $id)->first();
|
||||
if($blacklist->status == "True")
|
||||
{
|
||||
$blacklist->status = "False";
|
||||
|
||||
public function blacklistChange($id)
|
||||
{
|
||||
try {
|
||||
$blacklist = TicketBlacklist::where('id', $id)->first();
|
||||
}
|
||||
catch (Exception $e){
|
||||
return redirect()->back()->with('warning', __('User not found on the server. Check the admin database or try again later.'));
|
||||
}
|
||||
if ($blacklist->status == 'True') {
|
||||
$blacklist->status = 'False';
|
||||
} else {
|
||||
$blacklist->status = "True";
|
||||
$blacklist->status = 'True';
|
||||
}
|
||||
$blacklist->update();
|
||||
return redirect()->back()->with('success', __('Successfully change status blacklist from, User name: ' . $blacklist->user->name));
|
||||
|
||||
return redirect()->back()->with('success', __('Successfully change status blacklist from, User name: '.$blacklist->user->name));
|
||||
}
|
||||
|
||||
public function dataTableBlacklist()
|
||||
{
|
||||
$query = TicketBlacklist::with(['user']);
|
||||
$query->select('ticket_blacklists.*');
|
||||
|
||||
return datatables($query)
|
||||
->editColumn('user', function (TicketBlacklist $blacklist) {
|
||||
return '<a href="' . route('admin.users.show', $blacklist->user->id) . '">' . $blacklist->user->name . '</a>';
|
||||
return '<a href="'.route('admin.users.show', $blacklist->user->id).'">'.$blacklist->user->name.'</a>';
|
||||
})
|
||||
->editColumn('status', function (TicketBlacklist $blacklist) {
|
||||
switch ($blacklist->status) {
|
||||
case 'True':
|
||||
$text = "Blocked";
|
||||
$text = 'Blocked';
|
||||
$badgeColor = 'badge-danger';
|
||||
break;
|
||||
default:
|
||||
$text = "Unblocked";
|
||||
$text = 'Unblocked';
|
||||
$badgeColor = 'badge-success';
|
||||
break;
|
||||
}
|
||||
|
||||
return '<span class="badge ' . $badgeColor . '">' . $text . '</span>';
|
||||
return '<span class="badge '.$badgeColor.'">'.$text.'</span>';
|
||||
})
|
||||
->editColumn('reason', function (TicketBlacklist $blacklist) {
|
||||
return $blacklist->reason;
|
||||
})
|
||||
->addColumn('actions', function (TicketBlacklist $blacklist) {
|
||||
return '
|
||||
<form class="d-inline" method="post" action="' . route('moderator.ticket.blacklist.change', ['id' => $blacklist->id ]) . '">
|
||||
' . csrf_field() . '
|
||||
' . method_field("POST") . '
|
||||
<button data-content="'.__("Change Status").'" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm text-white btn-warning mr-1"><i class="fas fa-sync-alt"></i></button>
|
||||
<form class="d-inline" method="post" action="'.route('moderator.ticket.blacklist.change', ['id' => $blacklist->id]).'">
|
||||
'.csrf_field().'
|
||||
'.method_field('POST').'
|
||||
<button data-content="'.__('Change Status').'" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm text-white btn-warning mr-1"><i class="fas fa-sync-alt"></i></button>
|
||||
</form>
|
||||
<form class="d-inline" method="post" action="' . route('moderator.ticket.blacklist.delete', ['id' => $blacklist->id ]) . '">
|
||||
' . csrf_field() . '
|
||||
' . method_field("POST") . '
|
||||
<button data-content="'.__("Delete").'" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm text-white btn-danger mr-1"><i class="fas fa-trash"></i></button>
|
||||
<form class="d-inline" method="post" action="'.route('moderator.ticket.blacklist.delete', ['id' => $blacklist->id]).'">
|
||||
'.csrf_field().'
|
||||
'.method_field('POST').'
|
||||
<button data-content="'.__('Delete').'" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm text-white btn-danger mr-1"><i class="fas fa-trash"></i></button>
|
||||
</form>
|
||||
';
|
||||
})
|
||||
|
@ -203,5 +266,4 @@ class TicketsController extends Controller
|
|||
->rawColumns(['user', 'status', 'reason', 'created_at', 'actions'])
|
||||
->make(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,8 +10,9 @@ class NotificationController extends Controller
|
|||
public function index()
|
||||
{
|
||||
$notifications = Auth::user()->notifications()->paginate();
|
||||
|
||||
return view('notifications.index')->with([
|
||||
'notifications' => $notifications
|
||||
'notifications' => $notifications,
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -21,17 +22,19 @@ class NotificationController extends Controller
|
|||
$notification = Auth::user()->notifications()->findOrFail($id);
|
||||
|
||||
$notification->markAsRead();
|
||||
|
||||
return view('notifications.show')->with([
|
||||
'notification' => $notification
|
||||
'notification' => $notification,
|
||||
]);
|
||||
}
|
||||
|
||||
public function readAll(){
|
||||
public function readAll()
|
||||
{
|
||||
$notifications = Auth::user()->notifications()->get();
|
||||
foreach($notifications as $notification){
|
||||
foreach ($notifications as $notification) {
|
||||
$notification->markAsRead();
|
||||
}
|
||||
return redirect()->back();
|
||||
|
||||
return redirect()->back();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,15 +16,18 @@ class ProductController extends Controller
|
|||
{
|
||||
/**
|
||||
* @description get product locations based on selected egg
|
||||
* @param Request $request
|
||||
* @param Egg $egg
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Egg $egg
|
||||
* @return Collection|JsonResponse
|
||||
*/
|
||||
public function getNodesBasedOnEgg(Request $request, Egg $egg)
|
||||
{
|
||||
if (is_null($egg->id)) return response()->json('Egg ID is required', '400');
|
||||
if (is_null($egg->id)) {
|
||||
return response()->json('Egg ID is required', '400');
|
||||
}
|
||||
|
||||
#get products that include this egg
|
||||
//get products that include this egg
|
||||
$products = Product::query()
|
||||
->with('nodes')
|
||||
->where('disabled', '=', false)
|
||||
|
@ -34,31 +37,33 @@ class ProductController extends Controller
|
|||
|
||||
$nodes = collect();
|
||||
|
||||
#filter unique nodes
|
||||
//filter unique nodes
|
||||
$products->each(function (Product $product) use ($nodes) {
|
||||
$product->nodes->each(function (Node $node) use ($nodes) {
|
||||
if (!$nodes->contains('id', $node->id) && !$node->disabled) {
|
||||
if (! $nodes->contains('id', $node->id) && ! $node->disabled) {
|
||||
$nodes->add($node);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
return $nodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description get product locations based on selected egg
|
||||
* @param Request $request
|
||||
* @param Egg $egg
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Egg $egg
|
||||
* @return Collection|JsonResponse
|
||||
*/
|
||||
public function getLocationsBasedOnEgg(Request $request, Egg $egg)
|
||||
{
|
||||
$nodes = $this->getNodesBasedOnEgg($request, $egg);
|
||||
foreach($nodes as $key => $node){
|
||||
foreach ($nodes as $key => $node) {
|
||||
$pteroNode = Pterodactyl::getNode($node->id);
|
||||
if($pteroNode['allocated_resources']['memory']>=($pteroNode['memory']*($pteroNode['memory_overallocate']+100)/100)||$pteroNode['allocated_resources']['disk']>=($pteroNode['disk']*($pteroNode['disk_overallocate']+100)/100)) $nodes->forget($key);
|
||||
if ($pteroNode['allocated_resources']['memory'] >= ($pteroNode['memory'] * ($pteroNode['memory_overallocate'] + 100) / 100) || $pteroNode['allocated_resources']['disk'] >= ($pteroNode['disk'] * ($pteroNode['disk_overallocate'] + 100) / 100)) {
|
||||
$nodes->forget($key);
|
||||
}
|
||||
}
|
||||
$locations = collect();
|
||||
|
||||
|
@ -67,7 +72,7 @@ class ProductController extends Controller
|
|||
/** @var Location $location */
|
||||
$location = $node->location;
|
||||
|
||||
if (!$locations->contains('id', $location->id)) {
|
||||
if (! $locations->contains('id', $location->id)) {
|
||||
$nodeIds = $nodes->map(function ($node) {
|
||||
return $node->id;
|
||||
});
|
||||
|
@ -84,13 +89,15 @@ class ProductController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* @param Node $node
|
||||
* @param Egg $egg
|
||||
* @param Node $node
|
||||
* @param Egg $egg
|
||||
* @return Collection|JsonResponse
|
||||
*/
|
||||
public function getProductsBasedOnNode(Egg $egg, Node $node)
|
||||
{
|
||||
if (is_null($egg->id) || is_null($node->id)) return response()->json('node and egg id is required', '400');
|
||||
if (is_null($egg->id) || is_null($node->id)) {
|
||||
return response()->json('node and egg id is required', '400');
|
||||
}
|
||||
|
||||
$products = Product::query()
|
||||
->where('disabled', '=', false)
|
||||
|
@ -103,8 +110,10 @@ class ProductController extends Controller
|
|||
->get();
|
||||
|
||||
$pteroNode = Pterodactyl::getNode($node->id);
|
||||
foreach($products as $key => $product){
|
||||
if($product->memory>($pteroNode['memory']*($pteroNode['memory_overallocate']+100)/100)-$pteroNode['allocated_resources']['memory']||$product->disk>($pteroNode['disk']*($pteroNode['disk_overallocate']+100)/100)-$pteroNode['allocated_resources']['disk']) $product->doesNotFit = true;
|
||||
foreach ($products as $key => $product) {
|
||||
if ($product->memory > ($pteroNode['memory'] * ($pteroNode['memory_overallocate'] + 100) / 100) - $pteroNode['allocated_resources']['memory'] || $product->disk > ($pteroNode['disk'] * ($pteroNode['disk_overallocate'] + 100) / 100) - $pteroNode['allocated_resources']['disk']) {
|
||||
$product->doesNotFit = true;
|
||||
}
|
||||
}
|
||||
|
||||
return $products;
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
|
||||
use App\Classes\Pterodactyl;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
|
@ -30,6 +29,7 @@ class ProfileController extends Controller
|
|||
$badgeColor = 'badge-secondary';
|
||||
break;
|
||||
}
|
||||
|
||||
return view('profile.index')->with([
|
||||
'user' => Auth::user(),
|
||||
'credits_reward_after_verify_discord' => config('SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_DISCORD'),
|
||||
|
@ -39,68 +39,81 @@ class ProfileController extends Controller
|
|||
]);
|
||||
}
|
||||
|
||||
public function selfDestroyUser()
|
||||
{
|
||||
$user = Auth::user();
|
||||
if ($user->role == "admin") return back()->with("error", "You cannot delete yourself as an admin!");
|
||||
|
||||
$user->delete();
|
||||
|
||||
return redirect('/login')->with('success', __('Account permanently deleted!'));
|
||||
}
|
||||
|
||||
/** Update the specified resource in storage.
|
||||
* @param Request $request
|
||||
* @param int $id
|
||||
* @param Request $request
|
||||
* @param int $id
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function update(Request $request, int $id)
|
||||
{
|
||||
//prevent other users from editing a user
|
||||
if ($id != Auth::user()->id) dd(401);
|
||||
if ($id != Auth::user()->id) {
|
||||
dd(401);
|
||||
}
|
||||
$user = User::findOrFail($id);
|
||||
|
||||
//update password if necessary
|
||||
if (!is_null($request->input('new_password'))) {
|
||||
if (! is_null($request->input('new_password'))) {
|
||||
|
||||
//validate password request
|
||||
$request->validate([
|
||||
'current_password' => [
|
||||
'required',
|
||||
function ($attribute, $value, $fail) use ($user) {
|
||||
if (!Hash::check($value, $user->password)) {
|
||||
$fail('The ' . $attribute . ' is invalid.');
|
||||
if (! Hash::check($value, $user->password)) {
|
||||
$fail('The '.$attribute.' is invalid.');
|
||||
}
|
||||
},
|
||||
],
|
||||
'new_password' => 'required|string|min:8',
|
||||
'new_password_confirmation' => 'required|same:new_password'
|
||||
'new_password_confirmation' => 'required|same:new_password',
|
||||
]);
|
||||
|
||||
//Update Users Password on Pterodactyl
|
||||
//Username,Mail,First and Lastname are required aswell
|
||||
$response = Pterodactyl::client()->patch('/application/users/'.$user->pterodactyl_id, [
|
||||
"password" => $request->input('new_password'),
|
||||
"username" => $request->input('name'),
|
||||
"first_name" => $request->input('name'),
|
||||
"last_name" => $request->input('name'),
|
||||
"email" => $request->input('email'),
|
||||
'password' => $request->input('new_password'),
|
||||
'username' => $request->input('name'),
|
||||
'first_name' => $request->input('name'),
|
||||
'last_name' => $request->input('name'),
|
||||
'email' => $request->input('email'),
|
||||
|
||||
]);
|
||||
if ($response->failed()) {
|
||||
throw ValidationException::withMessages([
|
||||
'pterodactyl_error_message' => $response->toException()->getMessage(),
|
||||
'pterodactyl_error_status' => $response->toException()->getCode()
|
||||
'pterodactyl_error_status' => $response->toException()->getCode(),
|
||||
]);
|
||||
}
|
||||
//update password
|
||||
$user->update([
|
||||
'password' => Hash::make($request->input('new_password')),
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
//validate request
|
||||
$request->validate([
|
||||
'name' => 'required|min:4|max:30|alpha_num|unique:users,name,' . $id . ',id',
|
||||
'email' => 'required|email|max:64|unique:users,email,' . $id . ',id',
|
||||
'avatar' => 'nullable'
|
||||
'name' => 'required|min:4|max:30|alpha_num|unique:users,name,'.$id.',id',
|
||||
'email' => 'required|email|max:64|unique:users,email,'.$id.',id',
|
||||
'avatar' => 'nullable',
|
||||
]);
|
||||
|
||||
//update avatar
|
||||
if (!is_null($request->input('avatar'))) {
|
||||
if (! is_null($request->input('avatar'))) {
|
||||
$avatar = json_decode($request->input('avatar'));
|
||||
if ($avatar->input->size > 3000000) abort(500);
|
||||
if ($avatar->input->size > 3000000) {
|
||||
abort(500);
|
||||
}
|
||||
|
||||
$user->update([
|
||||
'avatar' => $avatar->output->image,
|
||||
|
@ -113,16 +126,16 @@ class ProfileController extends Controller
|
|||
|
||||
//update name and email on Pterodactyl
|
||||
$response = Pterodactyl::client()->patch('/application/users/'.$user->pterodactyl_id, [
|
||||
"username" => $request->input('name'),
|
||||
"first_name" => $request->input('name'),
|
||||
"last_name" => $request->input('name'),
|
||||
"email" => $request->input('email'),
|
||||
'username' => $request->input('name'),
|
||||
'first_name' => $request->input('name'),
|
||||
'last_name' => $request->input('name'),
|
||||
'email' => $request->input('email'),
|
||||
]);
|
||||
|
||||
if ($response->failed()) {
|
||||
throw ValidationException::withMessages([
|
||||
'pterodactyl_error_message' => $response->toException()->getMessage(),
|
||||
'pterodactyl_error_status' => $response->toException()->getCode()
|
||||
'pterodactyl_error_status' => $response->toException()->getCode(),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -135,7 +148,7 @@ class ProfileController extends Controller
|
|||
if ($request->input('email') != Auth::user()->email) {
|
||||
$user->reVerifyEmail();
|
||||
$user->sendEmailVerificationNotification();
|
||||
};
|
||||
}
|
||||
|
||||
return redirect()->route('profile.index')->with('success', __('Profile updated'));
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ use App\Models\Nest;
|
|||
use App\Models\Node;
|
||||
use App\Models\Product;
|
||||
use App\Models\Server;
|
||||
use App\Models\Settings;
|
||||
use App\Notifications\ServerCreationError;
|
||||
use Exception;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
@ -31,7 +30,9 @@ class ServerController extends Controller
|
|||
|
||||
//Get server infos from ptero
|
||||
$serverAttributes = Pterodactyl::getServerAttributes($server->pterodactyl_id, true);
|
||||
if(!$serverAttributes) continue;
|
||||
if (! $serverAttributes) {
|
||||
continue;
|
||||
}
|
||||
$serverRelationships = $serverAttributes['relationships'];
|
||||
$serverLocationAttributes = $serverRelationships['location']['attributes'];
|
||||
|
||||
|
@ -47,7 +48,7 @@ class ServerController extends Controller
|
|||
|
||||
//Check if a server got renamed on Pterodactyl
|
||||
$savedServer = Server::query()->where('id', $server->id)->first();
|
||||
if($savedServer->name != $serverAttributes['name']){
|
||||
if ($savedServer->name != $serverAttributes['name']) {
|
||||
$savedServer->name = $serverAttributes['name'];
|
||||
$server->name = $serverAttributes['name'];
|
||||
$savedServer->save();
|
||||
|
@ -59,14 +60,16 @@ class ServerController extends Controller
|
|||
}
|
||||
|
||||
return view('servers.index')->with([
|
||||
'servers' => $servers
|
||||
'servers' => $servers,
|
||||
]);
|
||||
}
|
||||
|
||||
/** Show the form for creating a new resource. */
|
||||
public function create()
|
||||
{
|
||||
if (!is_null($this->validateConfigurationRules())) return $this->validateConfigurationRules();
|
||||
if (! is_null($this->validateConfigurationRules())) {
|
||||
return $this->validateConfigurationRules();
|
||||
}
|
||||
|
||||
$productCount = Product::query()->where('disabled', '=', false)->count();
|
||||
$locations = Location::all();
|
||||
|
@ -90,11 +93,11 @@ class ServerController extends Controller
|
|||
|
||||
return view('servers.create')->with([
|
||||
'productCount' => $productCount,
|
||||
'nodeCount' => $nodeCount,
|
||||
'nests' => $nests,
|
||||
'locations' => $locations,
|
||||
'eggs' => $eggs,
|
||||
'user' => Auth::user(),
|
||||
'nodeCount' => $nodeCount,
|
||||
'nests' => $nests,
|
||||
'locations' => $locations,
|
||||
'eggs' => $eggs,
|
||||
'user' => Auth::user(),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -109,8 +112,8 @@ class ServerController extends Controller
|
|||
}
|
||||
|
||||
// minimum credits && Check for Allocation
|
||||
if (FacadesRequest::has("product")) {
|
||||
$product = Product::findOrFail(FacadesRequest::input("product"));
|
||||
if (FacadesRequest::has('product')) {
|
||||
$product = Product::findOrFail(FacadesRequest::input('product'));
|
||||
|
||||
// Get node resource allocation info
|
||||
$node = $product->nodes()->findOrFail(FacadesRequest::input('node'));
|
||||
|
@ -118,7 +121,9 @@ class ServerController extends Controller
|
|||
|
||||
// Check if node has enough memory and disk space
|
||||
$checkResponse = Pterodactyl::checkNodeResources($node, $product->memory, $product->disk);
|
||||
if ($checkResponse == False) return redirect()->route('servers.index')->with('error', __("The node '" . $nodeName . "' doesn't have the required memory or disk left to allocate this product."));
|
||||
if ($checkResponse == false) {
|
||||
return redirect()->route('servers.index')->with('error', __("The node '".$nodeName."' doesn't have the required memory or disk left to allocate this product."));
|
||||
}
|
||||
|
||||
// Min. Credits
|
||||
if (
|
||||
|
@ -127,24 +132,24 @@ class ServerController extends Controller
|
|||
? config('SETTINGS::USER:MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER', 50)
|
||||
: $product->minimum_credits)
|
||||
) {
|
||||
return redirect()->route('servers.index')->with('error', "You do not have the required amount of " . CREDITS_DISPLAY_NAME . " to use this product!");
|
||||
return redirect()->route('servers.index')->with('error', 'You do not have the required amount of '.CREDITS_DISPLAY_NAME.' to use this product!');
|
||||
}
|
||||
}
|
||||
|
||||
//Required Verification for creating an server
|
||||
if (config('SETTINGS::USER:FORCE_EMAIL_VERIFICATION', 'false') === 'true' && !Auth::user()->hasVerifiedEmail()) {
|
||||
return redirect()->route('profile.index')->with('error', __("You are required to verify your email address before you can create a server."));
|
||||
}
|
||||
|
||||
//Required Verification for creating an server
|
||||
|
||||
if (!config('SETTINGS::SYSTEM:CREATION_OF_NEW_SERVERS', 'true') && Auth::user()->role != "admin") {
|
||||
return redirect()->route('servers.index')->with('error', __("The system administrator has blocked the creation of new servers."));
|
||||
if (config('SETTINGS::USER:FORCE_EMAIL_VERIFICATION', 'false') === 'true' && ! Auth::user()->hasVerifiedEmail()) {
|
||||
return redirect()->route('profile.index')->with('error', __('You are required to verify your email address before you can create a server.'));
|
||||
}
|
||||
|
||||
//Required Verification for creating an server
|
||||
if (config('SETTINGS::USER:FORCE_DISCORD_VERIFICATION', 'false') === 'true' && !Auth::user()->discordUser) {
|
||||
return redirect()->route('profile.index')->with('error', __("You are required to link your discord account before you can create a server."));
|
||||
|
||||
if (! config('SETTINGS::SYSTEM:CREATION_OF_NEW_SERVERS', 'true') && Auth::user()->role != 'admin') {
|
||||
return redirect()->route('servers.index')->with('error', __('The system administrator has blocked the creation of new servers.'));
|
||||
}
|
||||
|
||||
//Required Verification for creating an server
|
||||
if (config('SETTINGS::USER:FORCE_DISCORD_VERIFICATION', 'false') === 'true' && ! Auth::user()->discordUser) {
|
||||
return redirect()->route('profile.index')->with('error', __('You are required to link your discord account before you can create a server.'));
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -156,14 +161,15 @@ class ServerController extends Controller
|
|||
/** @var Node $node */
|
||||
/** @var Egg $egg */
|
||||
/** @var Product $product */
|
||||
|
||||
if (!is_null($this->validateConfigurationRules())) return $this->validateConfigurationRules();
|
||||
if (! is_null($this->validateConfigurationRules())) {
|
||||
return $this->validateConfigurationRules();
|
||||
}
|
||||
|
||||
$request->validate([
|
||||
"name" => "required|max:191",
|
||||
"node" => "required|exists:nodes,id",
|
||||
"egg" => "required|exists:eggs,id",
|
||||
"product" => "required|exists:products,id"
|
||||
'name' => 'required|max:191',
|
||||
'node' => 'required|exists:nodes,id',
|
||||
'egg' => 'required|exists:eggs,id',
|
||||
'product' => 'required|exists:products,id',
|
||||
]);
|
||||
|
||||
//get required resources
|
||||
|
@ -172,23 +178,27 @@ class ServerController extends Controller
|
|||
$node = $product->nodes()->findOrFail($request->input('node'));
|
||||
|
||||
$server = $request->user()->servers()->create([
|
||||
'name' => $request->input('name'),
|
||||
'name' => $request->input('name'),
|
||||
'product_id' => $request->input('product'),
|
||||
]);
|
||||
|
||||
//get free allocation ID
|
||||
$allocationId = Pterodactyl::getFreeAllocationId($node);
|
||||
if (!$allocationId) return $this->noAllocationsError($server);
|
||||
if (! $allocationId) {
|
||||
return $this->noAllocationsError($server);
|
||||
}
|
||||
|
||||
//create server on pterodactyl
|
||||
$response = Pterodactyl::createServer($server, $egg, $allocationId);
|
||||
if ($response->failed()) return $this->serverCreationFailed($response, $server);
|
||||
if ($response->failed()) {
|
||||
return $this->serverCreationFailed($response, $server);
|
||||
}
|
||||
|
||||
$serverAttributes = $response->json()['attributes'];
|
||||
//update server with pterodactyl_id
|
||||
$server->update([
|
||||
'pterodactyl_id' => $serverAttributes['id'],
|
||||
'identifier' => $serverAttributes['identifier']
|
||||
'identifier' => $serverAttributes['identifier'],
|
||||
]);
|
||||
|
||||
if (config('SETTINGS::SYSTEM:SERVER_CREATE_CHARGE_FIRST_HOUR', 'true') == 'true') {
|
||||
|
@ -202,7 +212,8 @@ class ServerController extends Controller
|
|||
|
||||
/**
|
||||
* return redirect with error
|
||||
* @param Server $server
|
||||
*
|
||||
* @param Server $server
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
private function noAllocationsError(Server $server)
|
||||
|
@ -210,13 +221,15 @@ class ServerController extends Controller
|
|||
$server->delete();
|
||||
|
||||
Auth::user()->notify(new ServerCreationError($server));
|
||||
|
||||
return redirect()->route('servers.index')->with('error', __('No allocations satisfying the requirements for automatic deployment on this node were found.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* return redirect with error
|
||||
* @param Response $response
|
||||
* @param Server $server
|
||||
*
|
||||
* @param Response $response
|
||||
* @param Server $server
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
private function serverCreationFailed(Response $response, Server $server)
|
||||
|
@ -231,18 +244,19 @@ class ServerController extends Controller
|
|||
{
|
||||
try {
|
||||
$server->delete();
|
||||
|
||||
return redirect()->route('servers.index')->with('success', __('Server removed'));
|
||||
} catch (Exception $e) {
|
||||
return redirect()->route('servers.index')->with('error', __('An exception has occurred while trying to remove a resource "') . $e->getMessage() . '"');
|
||||
return redirect()->route('servers.index')->with('error', __('An exception has occurred while trying to remove a resource "').$e->getMessage().'"');
|
||||
}
|
||||
}
|
||||
|
||||
/** Show Server Settings */
|
||||
public function show(Server $server)
|
||||
{
|
||||
|
||||
|
||||
if($server->user_id != Auth::user()->id){ return back()->with('error', __('´This is not your Server!'));}
|
||||
if ($server->user_id != Auth::user()->id) {
|
||||
return back()->with('error', __('´This is not your Server!'));
|
||||
}
|
||||
$serverAttributes = Pterodactyl::getServerAttributes($server->pterodactyl_id);
|
||||
$serverRelationships = $serverAttributes['relationships'];
|
||||
$serverLocationAttributes = $serverRelationships['location']['attributes'];
|
||||
|
@ -261,7 +275,7 @@ class ServerController extends Controller
|
|||
|
||||
$pteroNode = Pterodactyl::getNode($serverRelationships['node']['attributes']['id']);
|
||||
|
||||
$products = Product::orderBy("created_at")
|
||||
$products = Product::orderBy('created_at')
|
||||
->whereHas('nodes', function (Builder $builder) use ($serverRelationships) { //Only show products for that node
|
||||
$builder->where('id', '=', $serverRelationships['node']['attributes']['id']);
|
||||
})
|
||||
|
@ -270,20 +284,23 @@ class ServerController extends Controller
|
|||
// Set the each product eggs array to just contain the eggs name
|
||||
foreach ($products as $product) {
|
||||
$product->eggs = $product->eggs->pluck('name')->toArray();
|
||||
if($product->memory-$currentProduct->memory>($pteroNode['memory']*($pteroNode['memory_overallocate']+100)/100)-$pteroNode['allocated_resources']['memory']||$product->disk-$currentProduct->disk>($pteroNode['disk']*($pteroNode['disk_overallocate']+100)/100)-$pteroNode['allocated_resources']['disk']) $product->doesNotFit = true;
|
||||
if ($product->memory - $currentProduct->memory > ($pteroNode['memory'] * ($pteroNode['memory_overallocate'] + 100) / 100) - $pteroNode['allocated_resources']['memory'] || $product->disk - $currentProduct->disk > ($pteroNode['disk'] * ($pteroNode['disk_overallocate'] + 100) / 100) - $pteroNode['allocated_resources']['disk']) {
|
||||
$product->doesNotFit = true;
|
||||
}
|
||||
}
|
||||
|
||||
return view('servers.settings')->with([
|
||||
'server' => $server,
|
||||
'products' => $products
|
||||
'products' => $products,
|
||||
]);
|
||||
}
|
||||
|
||||
public function upgrade(Server $server, Request $request)
|
||||
{
|
||||
if($server->user_id != Auth::user()->id) return redirect()->route('servers.index');
|
||||
if(!isset($request->product_upgrade))
|
||||
{
|
||||
if ($server->user_id != Auth::user()->id) {
|
||||
return redirect()->route('servers.index');
|
||||
}
|
||||
if (! isset($request->product_upgrade)) {
|
||||
return redirect()->route('servers.show', ['server' => $server->id])->with('error', __('this product is the only one'));
|
||||
}
|
||||
$user = Auth::user();
|
||||
|
@ -299,32 +316,35 @@ class ServerController extends Controller
|
|||
|
||||
// Check if node has enough memory and disk space
|
||||
$requireMemory = $newProduct->memory - $oldProduct->memory;
|
||||
$requiredisk = $newProduct->disk - $oldProduct->disk;
|
||||
$requiredisk = $newProduct->disk - $oldProduct->disk;
|
||||
$checkResponse = Pterodactyl::checkNodeResources($node, $requireMemory, $requiredisk);
|
||||
if ($checkResponse == False) return redirect()->route('servers.index')->with('error', __("The node '" . $nodeName . "' doesn't have the required memory or disk left to upgrade the server."));
|
||||
if ($checkResponse == false) {
|
||||
return redirect()->route('servers.index')->with('error', __("The node '".$nodeName."' doesn't have the required memory or disk left to upgrade the server."));
|
||||
}
|
||||
|
||||
$priceupgrade = $newProduct->getHourlyPrice();
|
||||
|
||||
if ($priceupgrade < $oldProduct->getHourlyPrice()) {
|
||||
$priceupgrade = 0;
|
||||
$priceupgrade = 0;
|
||||
}
|
||||
if ($user->credits >= $priceupgrade && $user->credits >= $newProduct->minimum_credits)
|
||||
{
|
||||
|
||||
if ($user->credits >= $priceupgrade && $user->credits >= $newProduct->minimum_credits) {
|
||||
$server->product_id = $request->product_upgrade;
|
||||
$server->update();
|
||||
$server->allocation = $serverAttributes['allocation'];
|
||||
$response = Pterodactyl::updateServer($server, $newProduct);
|
||||
if ($response->failed()) return $this->serverCreationFailed($response, $server);
|
||||
if ($response->failed()) {
|
||||
return $this->serverCreationFailed($response, $server);
|
||||
}
|
||||
//update user balance
|
||||
$user->decrement('credits', $priceupgrade);
|
||||
//restart the server
|
||||
$response = Pterodactyl::powerAction($server, "restart");
|
||||
if ($response->failed()) return redirect()->route('servers.index')->with('error', $response->json()['errors'][0]['detail']);
|
||||
$response = Pterodactyl::powerAction($server, 'restart');
|
||||
if ($response->failed()) {
|
||||
return redirect()->route('servers.index')->with('error', $response->json()['errors'][0]['detail']);
|
||||
}
|
||||
|
||||
return redirect()->route('servers.show', ['server' => $server->id])->with('success', __('Server Successfully Upgraded'));
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
return redirect()->route('servers.show', ['server' => $server->id])->with('error', __('Not Enough Balance for Upgrade'));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\ShopProduct;
|
||||
use App\Models\Settings;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class StoreController extends Controller
|
||||
|
@ -15,18 +14,20 @@ class StoreController extends Controller
|
|||
|
||||
if (
|
||||
env('APP_ENV') == 'local' ||
|
||||
config("SETTINGS::PAYMENTS:PAYPAL:SECRET") && config("SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID") ||
|
||||
config("SETTINGS::PAYMENTS:STRIPE:SECRET") && config("SETTINGS::PAYMENTS:STRIPE:ENDPOINT_SECRET") && config("SETTINGS::PAYMENTS:STRIPE:METHODS")
|
||||
) $isPaymentSetup = true;
|
||||
|
||||
//Required Verification for creating an server
|
||||
if (config('SETTINGS::USER:FORCE_EMAIL_VERIFICATION', false) === 'true' && !Auth::user()->hasVerifiedEmail()) {
|
||||
return redirect()->route('profile.index')->with('error', __("You are required to verify your email address before you can purchase credits."));
|
||||
config('SETTINGS::PAYMENTS:PAYPAL:SECRET') && config('SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID') ||
|
||||
config('SETTINGS::PAYMENTS:STRIPE:SECRET') && config('SETTINGS::PAYMENTS:STRIPE:ENDPOINT_SECRET') && config('SETTINGS::PAYMENTS:STRIPE:METHODS')
|
||||
) {
|
||||
$isPaymentSetup = true;
|
||||
}
|
||||
|
||||
//Required Verification for creating an server
|
||||
if (config('SETTINGS::USER:FORCE_DISCORD_VERIFICATION', false) === 'true' && !Auth::user()->discordUser) {
|
||||
return redirect()->route('profile.index')->with('error', __("You are required to link your discord account before you can purchase Credits"));
|
||||
if (config('SETTINGS::USER:FORCE_EMAIL_VERIFICATION', false) === 'true' && ! Auth::user()->hasVerifiedEmail()) {
|
||||
return redirect()->route('profile.index')->with('error', __('You are required to verify your email address before you can purchase credits.'));
|
||||
}
|
||||
|
||||
//Required Verification for creating an server
|
||||
if (config('SETTINGS::USER:FORCE_DISCORD_VERIFICATION', false) === 'true' && ! Auth::user()->discordUser) {
|
||||
return redirect()->route('profile.index')->with('error', __('You are required to link your discord account before you can purchase Credits'));
|
||||
}
|
||||
|
||||
return view('store.index')->with([
|
||||
|
|
|
@ -2,113 +2,157 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
|
||||
use App\Models\Ticket;
|
||||
use App\Models\Server;
|
||||
use App\Models\TicketComment;
|
||||
use App\Models\TicketCategory;
|
||||
use App\Models\Ticket;
|
||||
use App\Models\TicketBlacklist;
|
||||
use App\Notifications\Ticket\User\CreateNotification;
|
||||
use App\Models\TicketCategory;
|
||||
use App\Models\TicketComment;
|
||||
use App\Models\User;
|
||||
use App\Notifications\Ticket\Admin\AdminCreateNotification;
|
||||
use App\Notifications\Ticket\Admin\AdminReplyNotification;
|
||||
|
||||
use App\Notifications\Ticket\User\CreateNotification;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class TicketsController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
$tickets = Ticket::where("user_id", Auth::user()->id)->paginate(10);
|
||||
$tickets = Ticket::where('user_id', Auth::user()->id)->paginate(10);
|
||||
$ticketcategories = TicketCategory::all();
|
||||
|
||||
return view("ticket.index", compact("tickets", "ticketcategories"));
|
||||
|
||||
return view('ticket.index', compact('tickets', 'ticketcategories'));
|
||||
}
|
||||
public function create() {
|
||||
#check in blacklist
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'title' => 'required',
|
||||
'ticketcategory' => 'required',
|
||||
'priority' => 'required',
|
||||
'message' => 'required',]
|
||||
);
|
||||
$ticket = new Ticket([
|
||||
'title' => $request->input('title'),
|
||||
'user_id' => Auth::user()->id,
|
||||
'ticket_id' => strtoupper(Str::random(8)),
|
||||
'ticketcategory_id' => $request->input('ticketcategory'),
|
||||
'priority' => $request->input('priority'),
|
||||
'message' => $request->input('message'),
|
||||
'status' => 'Open',
|
||||
'server' => $request->input('server'),]
|
||||
);
|
||||
$ticket->save();
|
||||
$user = Auth::user();
|
||||
if (config('SETTINGS::TICKET:NOTIFY') == "all") {
|
||||
$admin = User::where('role', 'admin')->orWhere('role', 'mod')->get();
|
||||
}
|
||||
if (config('SETTINGS::TICKET:NOTIFY') == "admin") {
|
||||
$admin = User::where('role', 'admin')->get();
|
||||
}
|
||||
if (config('SETTINGS::TICKET:NOTIFY') == "moderator") {
|
||||
$admin = User::where('role', 'mod')->get();
|
||||
}
|
||||
$user->notify(new CreateNotification($ticket));
|
||||
if (config('SETTINGS::TICKET:NOTIFY') != "none") {
|
||||
Notification::send($admin, new AdminCreateNotification($ticket, $user));
|
||||
}
|
||||
|
||||
return redirect()->route('ticket.index')->with('success', __('A ticket has been opened, ID: #') . $ticket->ticket_id);
|
||||
}
|
||||
|
||||
public function show($ticket_id)
|
||||
{
|
||||
try {
|
||||
$ticket = Ticket::where('ticket_id', $ticket_id)->firstOrFail();
|
||||
} catch (Exception $e) {
|
||||
return redirect()->back()->with('warning', __('Ticket not found on the server. It potentially got deleted earlier'));
|
||||
}
|
||||
$ticketcomments = $ticket->ticketcomments;
|
||||
$ticketcategory = $ticket->ticketcategory;
|
||||
$server = Server::where('id', $ticket->server)->first();
|
||||
|
||||
return view('ticket.show', compact('ticket', 'ticketcategory', 'ticketcomments', 'server'));
|
||||
}
|
||||
|
||||
public function reply(Request $request)
|
||||
{
|
||||
//check in blacklist
|
||||
$check = TicketBlacklist::where('user_id', Auth::user()->id)->first();
|
||||
if($check && $check->status == "True"){
|
||||
if ($check && $check->status == 'True') {
|
||||
return redirect()->route('ticket.index')->with('error', __("You can't reply a ticket because you're on the blacklist for a reason: '" . $check->reason . "', please contact the administrator"));
|
||||
}
|
||||
$this->validate($request, ['ticketcomment' => 'required']);
|
||||
try {
|
||||
$ticket = Ticket::where('id', $request->input('ticket_id'))->firstOrFail();
|
||||
} catch (Exception $e) {
|
||||
return redirect()->back()->with('warning', __('Ticket not found on the server. It potentially got deleted earlier'));
|
||||
}
|
||||
$ticket->status = 'Client Reply';
|
||||
$ticket->update();
|
||||
$ticketcomment = TicketComment::create([
|
||||
'ticket_id' => $request->input('ticket_id'),
|
||||
'user_id' => Auth::user()->id,
|
||||
'ticketcomment' => $request->input('ticketcomment'),
|
||||
'message' => $request->input('message'),
|
||||
]);
|
||||
$user = Auth::user();
|
||||
$admin = User::where('role', 'admin')->orWhere('role', 'mod')->get();
|
||||
$newmessage = $request->input('ticketcomment');
|
||||
Notification::send($admin, new AdminReplyNotification($ticket, $user, $newmessage));
|
||||
|
||||
return redirect()->back()->with('success', __('Your comment has been submitted'));
|
||||
}
|
||||
|
||||
public function create()
|
||||
{
|
||||
//check in blacklist
|
||||
$check = TicketBlacklist::where('user_id', Auth::user()->id)->first();
|
||||
if ($check && $check->status == 'True') {
|
||||
return redirect()->route('ticket.index')->with('error', __("You can't make a ticket because you're on the blacklist for a reason: '" . $check->reason . "', please contact the administrator"));
|
||||
}
|
||||
$ticketcategories = TicketCategory::all();
|
||||
$servers = Auth::user()->servers;
|
||||
return view("ticket.create", compact("ticketcategories", "servers"));
|
||||
|
||||
return view('ticket.create', compact('ticketcategories', 'servers'));
|
||||
}
|
||||
public function store(Request $request) {
|
||||
$this->validate($request, array(
|
||||
"title" => "required",
|
||||
"ticketcategory" => "required",
|
||||
"priority" => "required",
|
||||
"message" => "required")
|
||||
);
|
||||
$ticket = new Ticket(array(
|
||||
"title" => $request->input("title"),
|
||||
"user_id" => Auth::user()->id,
|
||||
"ticket_id" => strtoupper(Str::random(5)),
|
||||
"ticketcategory_id" => $request->input("ticketcategory"),
|
||||
"priority" => $request->input("priority"),
|
||||
"message" => $request->input("message"),
|
||||
"status" => "Open",
|
||||
"server" => $request->input("server"))
|
||||
);
|
||||
$ticket->save();
|
||||
$user = Auth::user();
|
||||
$admin = User::where('role', 'admin')->orWhere('role', 'mod')->get();
|
||||
$user->notify(new CreateNotification($ticket));
|
||||
Notification::send($admin, new AdminCreateNotification($ticket, $user));
|
||||
|
||||
return redirect()->route('ticket.index')->with('success', __('A ticket has been opened, ID: #') . $ticket->ticket_id);
|
||||
}
|
||||
public function show($ticket_id) {
|
||||
$ticket = Ticket::where("ticket_id", $ticket_id)->firstOrFail();
|
||||
$ticketcomments = $ticket->ticketcomments;
|
||||
$ticketcategory = $ticket->ticketcategory;
|
||||
$server = Server::where('id', $ticket->server)->first();
|
||||
return view("ticket.show", compact("ticket", "ticketcategory", "ticketcomments", "server"));
|
||||
}
|
||||
public function reply(Request $request) {
|
||||
#check in blacklist
|
||||
$check = TicketBlacklist::where('user_id', Auth::user()->id)->first();
|
||||
if($check && $check->status == "True"){
|
||||
return redirect()->route('ticket.index')->with('error', __("You can't reply a ticket because you're on the blacklist for a reason: '" . $check->reason . "', please contact the administrator"));
|
||||
|
||||
public function changeStatus($ticket_id)
|
||||
{
|
||||
try {
|
||||
$ticket = Ticket::where('user_id', Auth::user()->id)->where("ticket_id", $ticket_id)->firstOrFail();
|
||||
} catch (Exception $e) {
|
||||
return redirect()->back()->with('warning', __('Ticket not found on the server. It potentially got deleted earlier'));
|
||||
}
|
||||
$this->validate($request, array("ticketcomment" => "required"));
|
||||
$ticket = Ticket::where('id', $request->input("ticket_id"))->firstOrFail();
|
||||
$ticket->status = "Client Reply";
|
||||
$ticket->update();
|
||||
$ticketcomment = TicketComment::create(array(
|
||||
"ticket_id" => $request->input("ticket_id"),
|
||||
"user_id" => Auth::user()->id,
|
||||
"ticketcomment" => $request->input("ticketcomment"),
|
||||
"message" => $request->input("message")
|
||||
));
|
||||
$user = Auth::user();
|
||||
$admin = User::where('role', 'admin')->orWhere('role', 'mod')->get();
|
||||
$newmessage = $request->input("ticketcomment");
|
||||
Notification::send($admin, new AdminReplyNotification($ticket, $user, $newmessage));
|
||||
return redirect()->back()->with('success', __('Your comment has been submitted'));
|
||||
if ($ticket->status == "Closed") {
|
||||
$ticket->status = "Reopened";
|
||||
$ticket->save();
|
||||
return redirect()->back()->with('success', __('A ticket has been reopened, ID: #') . $ticket->ticket_id);
|
||||
}
|
||||
$ticket->status = "Closed";
|
||||
$ticket->save();
|
||||
return redirect()->back()->with('success', __('A ticket has been closed, ID: #') . $ticket->ticket_id);
|
||||
}
|
||||
|
||||
public function dataTable()
|
||||
{
|
||||
$query = Ticket::where("user_id", Auth::user()->id)->get();
|
||||
$query = Ticket::where('user_id', Auth::user()->id)->get();
|
||||
|
||||
return datatables($query)
|
||||
->addColumn('category', function (Ticket $tickets) {
|
||||
return $tickets->ticketcategory->name;
|
||||
})
|
||||
->editColumn('title', function (Ticket $tickets) {
|
||||
return '<a class="text-info" href="' . route('ticket.show', ['ticket_id' => $tickets->ticket_id]) . '">' . "#" . $tickets->ticket_id . " - " . $tickets->title . '</a>';
|
||||
return '<a class="text-info" href="' . route('ticket.show', ['ticket_id' => $tickets->ticket_id]) . '">' . '#' . $tickets->ticket_id . ' - ' . htmlspecialchars($tickets->title) . '</a>';
|
||||
})
|
||||
->editColumn('status', function (Ticket $tickets) {
|
||||
switch ($tickets->status) {
|
||||
case 'Reopened':
|
||||
case 'Open':
|
||||
$badgeColor = 'badge-success';
|
||||
break;
|
||||
break;
|
||||
case 'Closed':
|
||||
$badgeColor = 'badge-danger';
|
||||
break;
|
||||
|
@ -122,10 +166,30 @@ class TicketsController extends Controller
|
|||
|
||||
return '<span class="badge ' . $badgeColor . '">' . $tickets->status . '</span>';
|
||||
})
|
||||
->editColumn('updated_at', function (Ticket $tickets) {
|
||||
return $tickets->updated_at ? $tickets->updated_at->diffForHumans() : '';
|
||||
->editColumn('priority', function (Ticket $tickets) {
|
||||
return __($tickets->priority);
|
||||
})
|
||||
->rawColumns(['category', 'title', 'status', 'updated_at'])
|
||||
->editColumn('updated_at', function (Ticket $tickets) {
|
||||
return ['display' => $tickets->updated_at ? $tickets->updated_at->diffForHumans() : '',
|
||||
'raw' => $tickets->updated_at ? strtotime($tickets->updated_at) : ''];
|
||||
})
|
||||
->addColumn('actions', function (Ticket $tickets) {
|
||||
$statusButtonColor = ($tickets->status == "Closed") ? 'btn-success' : 'btn-warning';
|
||||
$statusButtonIcon = ($tickets->status == "Closed") ? 'fa-redo' : 'fa-times';
|
||||
$statusButtonText = ($tickets->status == "Closed") ? __('Reopen') : __('Close');
|
||||
|
||||
return '
|
||||
<a data-content="' . __('View') . '" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('ticket.show', ['ticket_id' => $tickets->ticket_id]) . '" class="btn btn-sm text-white btn-info mr-1"><i class="fas fa-eye"></i></a>
|
||||
<form class="d-inline" method="post" action="' . route('ticket.changeStatus', ['ticket_id' => $tickets->ticket_id]) . '">
|
||||
' . csrf_field() . '
|
||||
' . method_field('POST') . '
|
||||
<button data-content="' . __($statusButtonText) . '" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm text-white ' . $statusButtonColor . ' mr-1"><i class="fas ' . $statusButtonIcon . '"></i></button>
|
||||
</form>
|
||||
|
||||
</form>
|
||||
';
|
||||
})
|
||||
->rawColumns(['category', 'title', 'status', 'updated_at', "actions"])
|
||||
->make(true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,16 +8,15 @@ use Illuminate\Support\Facades\Session;
|
|||
class TranslationController extends Controller
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Change session locale
|
||||
* @param Request $request
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function changeLocale(Request $request)
|
||||
{
|
||||
Session::put('locale', $request->inputLocale);
|
||||
|
||||
return redirect()->back();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ class Kernel extends HttpKernel
|
|||
protected $middleware = [
|
||||
// \App\Http\Middleware\TrustHosts::class,
|
||||
\App\Http\Middleware\TrustProxies::class,
|
||||
\Fruitcake\Cors\HandleCors::class,
|
||||
\Illuminate\Http\Middleware\HandleCors::class,
|
||||
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
|
||||
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
|
||||
\App\Http\Middleware\TrimStrings::class,
|
||||
|
@ -39,7 +39,6 @@ class Kernel extends HttpKernel
|
|||
\App\Http\Middleware\EncryptCookies::class,
|
||||
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
|
||||
\Illuminate\Session\Middleware\StartSession::class,
|
||||
// \Illuminate\Session\Middleware\AuthenticateSession::class,
|
||||
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
|
||||
\App\Http\Middleware\VerifyCsrfToken::class,
|
||||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
|
@ -51,7 +50,7 @@ class Kernel extends HttpKernel
|
|||
'api' => [
|
||||
'throttle:api',
|
||||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
GlobalNames::class
|
||||
GlobalNames::class,
|
||||
],
|
||||
];
|
||||
|
||||
|
@ -65,6 +64,7 @@ class Kernel extends HttpKernel
|
|||
protected $routeMiddleware = [
|
||||
'auth' => \App\Http\Middleware\Authenticate::class,
|
||||
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
|
||||
'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
|
||||
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
|
||||
'can' => \Illuminate\Auth\Middleware\Authorize::class,
|
||||
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
|
||||
|
@ -75,6 +75,6 @@ class Kernel extends HttpKernel
|
|||
'admin' => isAdmin::class,
|
||||
'moderator' => isMod::class,
|
||||
'api.token' => ApiAuthToken::class,
|
||||
'checkSuspended' => CheckSuspended::class
|
||||
'checkSuspended' => CheckSuspended::class,
|
||||
];
|
||||
}
|
||||
|
|
|
@ -11,18 +11,23 @@ class ApiAuthToken
|
|||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Closure $next
|
||||
* @param Request $request
|
||||
* @param Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
if (empty($request->bearerToken())) return response()->json(['message' => 'Missing Authorization header'], 403);
|
||||
if (empty($request->bearerToken())) {
|
||||
return response()->json(['message' => 'Missing Authorization header'], 403);
|
||||
}
|
||||
|
||||
$token = ApplicationApi::find($request->bearerToken());
|
||||
if (is_null($token)) return response()->json(['message' => 'Invalid Authorization token'], 401);
|
||||
if (is_null($token)) {
|
||||
return response()->json(['message' => 'Invalid Authorization token'], 401);
|
||||
}
|
||||
|
||||
$token->updateLastUsed();
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ class CheckSuspended
|
|||
|
||||
return redirect()->route('login')->withMessage($message);
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Models\Configuration;
|
||||
use App\Models\Settings;
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
|
@ -12,15 +10,15 @@ class GlobalNames
|
|||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Closure $next
|
||||
* @param Request $request
|
||||
* @param Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
define('CREDITS_DISPLAY_NAME', config('SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME', 'Credits'));
|
||||
|
||||
$unsupported_lang_array = explode(',', config("app.unsupported_locales"));
|
||||
$unsupported_lang_array = explode(',', config('app.unsupported_locales'));
|
||||
$unsupported_lang_array = array_map('strtolower', $unsupported_lang_array);
|
||||
define('UNSUPPORTED_LANGS', $unsupported_lang_array);
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use DateTime;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
|
@ -12,17 +11,17 @@ class LastSeen
|
|||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Closure $next
|
||||
* @param Request $request
|
||||
* @param Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
if (env('APP_ENV' , 'local') == 'local'){
|
||||
if (env('APP_ENV', 'local') == 'local') {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
if (!Auth::check()) {
|
||||
if (! Auth::check()) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
|
@ -32,7 +31,7 @@ class LastSeen
|
|||
|
||||
Auth::user()->update([
|
||||
'last_seen' => now(),
|
||||
'ip' => $request->ip()
|
||||
'ip' => $request->ip(),
|
||||
]);
|
||||
|
||||
return $next($request);
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Models\Settings;
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\App;
|
||||
|
@ -10,27 +9,25 @@ use Illuminate\Support\Facades\Session;
|
|||
|
||||
class SetLocale
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Closure $next
|
||||
* @param Request $request
|
||||
* @param Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
if (Session::has('locale')) {
|
||||
$locale = Session::get('locale', config("SETTINGS::LOCALE:DEFAULT"));
|
||||
$locale = Session::get('locale', config('SETTINGS::LOCALE:DEFAULT'));
|
||||
} else {
|
||||
if (config("SETTINGS::LOCALE:DYNAMIC") !== "true") {
|
||||
$locale = config("SETTINGS::LOCALE:DEFAULT");
|
||||
if (config('SETTINGS::LOCALE:DYNAMIC') !== 'true') {
|
||||
$locale = config('SETTINGS::LOCALE:DEFAULT');
|
||||
} else {
|
||||
$locale = substr($request->server('HTTP_ACCEPT_LANGUAGE'), 0, 2);
|
||||
|
||||
if (!in_array($locale, explode(',', config("SETTINGS::LOCALE:AVAILABLE")))) {
|
||||
$locale = config("SETTINGS::LOCALE:DEFAULT");
|
||||
if (! in_array($locale, explode(',', config('SETTINGS::LOCALE:AVAILABLE')))) {
|
||||
$locale = config('SETTINGS::LOCALE:DEFAULT');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,9 +9,10 @@ class TrimStrings extends Middleware
|
|||
/**
|
||||
* The names of the attributes that should not be trimmed.
|
||||
*
|
||||
* @var array
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $except = [
|
||||
'current_password',
|
||||
'password',
|
||||
'password_confirmation',
|
||||
];
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Fideloper\Proxy\TrustProxies as Middleware;
|
||||
use Illuminate\Http\Middleware\TrustProxies as Middleware;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class TrustProxies extends Middleware
|
||||
|
@ -10,7 +10,7 @@ class TrustProxies extends Middleware
|
|||
/**
|
||||
* The trusted proxies for this application.
|
||||
*
|
||||
* @var array|string|null
|
||||
* @var array<int, string>|string|null
|
||||
*/
|
||||
protected $proxies;
|
||||
|
||||
|
@ -19,5 +19,10 @@ class TrustProxies extends Middleware
|
|||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $headers = Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO | Request::HEADER_X_FORWARDED_AWS_ELB;
|
||||
protected $headers =
|
||||
Request::HEADER_X_FORWARDED_FOR |
|
||||
Request::HEADER_X_FORWARDED_HOST |
|
||||
Request::HEADER_X_FORWARDED_PORT |
|
||||
Request::HEADER_X_FORWARDED_PROTO |
|
||||
Request::HEADER_X_FORWARDED_AWS_ELB;
|
||||
}
|
||||
|
|
22
app/Http/Middleware/ValidateSignature.php
Normal file
22
app/Http/Middleware/ValidateSignature.php
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Routing\Middleware\ValidateSignature as Middleware;
|
||||
|
||||
class ValidateSignature extends Middleware
|
||||
{
|
||||
/**
|
||||
* The names of the query string parameters that should be ignored.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $except = [
|
||||
// 'fbclid',
|
||||
// 'utm_campaign',
|
||||
// 'utm_content',
|
||||
// 'utm_medium',
|
||||
// 'utm_source',
|
||||
// 'utm_term',
|
||||
];
|
||||
}
|
|
@ -2,7 +2,10 @@
|
|||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Helpers\ExtensionHelper;
|
||||
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
|
||||
use Illuminate\Contracts\Encryption\Encrypter;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
|
||||
class VerifyCsrfToken extends Middleware
|
||||
{
|
||||
|
@ -11,7 +14,12 @@ class VerifyCsrfToken extends Middleware
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $except = [
|
||||
'payment/StripeWebhooks'
|
||||
];
|
||||
protected $except = [];
|
||||
|
||||
public function __construct(Application $app, Encrypter $encrypter)
|
||||
{
|
||||
$this->app = $app;
|
||||
$this->encrypter = $encrypter;
|
||||
$this->except = ExtensionHelper::getAllCsrfIgnoredRoutes();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,8 +12,8 @@ class isAdmin
|
|||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Closure $next
|
||||
* @param Request $request
|
||||
* @param Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
|
|
|
@ -12,8 +12,8 @@ class isMod
|
|||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Closure $next
|
||||
* @param Request $request
|
||||
* @param Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
|
|
26
app/Listeners/CreateInvoice.php
Normal file
26
app/Listeners/CreateInvoice.php
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
namespace App\Listeners;
|
||||
|
||||
use App\Events\PaymentEvent;
|
||||
use App\Traits\Invoiceable;
|
||||
|
||||
class CreateInvoice
|
||||
{
|
||||
|
||||
use Invoiceable;
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param \App\Events\PaymentEvent $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(PaymentEvent $event)
|
||||
{
|
||||
if (config('SETTINGS::INVOICE:ENABLED') == 'true') {
|
||||
// create invoice using the trait
|
||||
$this->createInvoice($event->payment, $event->shopProduct);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,7 +4,6 @@ namespace App\Listeners;
|
|||
|
||||
use App\Events\UserUpdateCreditsEvent;
|
||||
use App\Models\Server;
|
||||
use App\Models\Settings;
|
||||
use Exception;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
||||
|
@ -13,8 +12,9 @@ class UnsuspendServers implements ShouldQueue
|
|||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param UserUpdateCreditsEvent $event
|
||||
* @param UserUpdateCreditsEvent $event
|
||||
* @return void
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function handle(UserUpdateCreditsEvent $event)
|
||||
|
@ -22,7 +22,9 @@ class UnsuspendServers implements ShouldQueue
|
|||
if ($event->user->credits > config('SETTINGS::USER:MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER', 50)) {
|
||||
/** @var Server $server */
|
||||
foreach ($event->user->servers as $server) {
|
||||
if ($server->isSuspended()) $server->unSuspend();
|
||||
if ($server->isSuspended()) {
|
||||
$server->unSuspend();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
82
app/Listeners/UserPayment.php
Normal file
82
app/Listeners/UserPayment.php
Normal file
|
@ -0,0 +1,82 @@
|
|||
<?php
|
||||
|
||||
namespace App\Listeners;
|
||||
|
||||
use App\Events\PaymentEvent;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Models\PartnerDiscount;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
|
||||
class UserPayment
|
||||
{
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param \App\Events\PaymentEvent $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(PaymentEvent $event)
|
||||
{
|
||||
$user = $event->user;
|
||||
$shopProduct = $event->shopProduct;
|
||||
|
||||
// only update user if payment is paid
|
||||
if ($event->payment->status != "paid") {
|
||||
return;
|
||||
}
|
||||
|
||||
//update server limit
|
||||
if (config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE') !== 0 && $user->server_limit < config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')) {
|
||||
$user->update(['server_limit' => config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')]);
|
||||
}
|
||||
|
||||
//update User with bought item
|
||||
if ($shopProduct->type == "Credits") {
|
||||
$user->increment('credits', $shopProduct->quantity);
|
||||
} elseif ($shopProduct->type == "Server slots") {
|
||||
$user->increment('server_limit', $shopProduct->quantity);
|
||||
}
|
||||
|
||||
//give referral commission always
|
||||
if ((config("SETTINGS::REFERRAL:MODE") == "commission" || config("SETTINGS::REFERRAL:MODE") == "both") && $shopProduct->type == "Credits" && config("SETTINGS::REFERRAL::ALWAYS_GIVE_COMMISSION") == "true") {
|
||||
if ($ref_user = DB::table("user_referrals")->where('registered_user_id', '=', $user->id)->first()) {
|
||||
$ref_user = User::findOrFail($ref_user->referral_id);
|
||||
$increment = number_format($shopProduct->quantity * (PartnerDiscount::getCommission($ref_user->id)) / 100, 0, "", "");
|
||||
$ref_user->increment('credits', $increment);
|
||||
|
||||
//LOGS REFERRALS IN THE ACTIVITY LOG
|
||||
activity()
|
||||
->performedOn($user)
|
||||
->causedBy($ref_user)
|
||||
->log('gained ' . $increment . ' ' . config("SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME") . ' for commission-referral of ' . $user->name . ' (ID:' . $user->id . ')');
|
||||
}
|
||||
}
|
||||
//update role give Referral-reward
|
||||
if ($user->role == 'member') {
|
||||
$user->update(['role' => 'client']);
|
||||
|
||||
//give referral commission only on first purchase
|
||||
if ((config("SETTINGS::REFERRAL:MODE") == "commission" || config("SETTINGS::REFERRAL:MODE") == "both") && $shopProduct->type == "Credits" && config("SETTINGS::REFERRAL::ALWAYS_GIVE_COMMISSION") == "false") {
|
||||
if ($ref_user = DB::table("user_referrals")->where('registered_user_id', '=', $user->id)->first()) {
|
||||
$ref_user = User::findOrFail($ref_user->referral_id);
|
||||
$increment = number_format($shopProduct->quantity * (PartnerDiscount::getCommission($ref_user->id)) / 100, 0, "", "");
|
||||
$ref_user->increment('credits', $increment);
|
||||
|
||||
//LOGS REFERRALS IN THE ACTIVITY LOG
|
||||
activity()
|
||||
->performedOn($user)
|
||||
->causedBy($ref_user)
|
||||
->log('gained ' . $increment . ' ' . config("SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME") . ' for commission-referral of ' . $user->name . ' (ID:' . $user->id . ')');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// LOGS PAYMENT IN THE ACTIVITY LOG
|
||||
activity()
|
||||
->performedOn($user)
|
||||
->causedBy($user)
|
||||
->log('bought ' . $shopProduct->quantity . ' ' . $shopProduct->type . ' for ' . $shopProduct->price . $shopProduct->currency_code);
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@ class Verified
|
|||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param object $event
|
||||
* @param object $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle($event)
|
||||
|
@ -25,6 +25,7 @@ class Verified
|
|||
if (!$event->user->email_verified_reward) {
|
||||
$event->user->increment('server_limit', config('SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_EMAIL'));
|
||||
$event->user->increment('credits', config('SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_EMAIL'));
|
||||
$event->user->update(['email_verified_reward' => true]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,13 +10,15 @@ class ApplicationApi extends Model
|
|||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = ['token', 'memo' , 'last_used'];
|
||||
protected $fillable = ['token', 'memo', 'last_used'];
|
||||
|
||||
protected $primaryKey = 'token';
|
||||
|
||||
public $incrementing = false;
|
||||
|
||||
protected $dates = ['last_used'];
|
||||
protected $casts = [
|
||||
'last_used' => 'datetime',
|
||||
];
|
||||
|
||||
public static function boot()
|
||||
{
|
||||
|
@ -29,7 +31,8 @@ class ApplicationApi extends Model
|
|||
});
|
||||
}
|
||||
|
||||
public function updateLastUsed(){
|
||||
public function updateLastUsed()
|
||||
{
|
||||
$this->update(['last_used' => now()]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,18 +11,18 @@ class DiscordUser extends Model
|
|||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
"id",
|
||||
"user_id",
|
||||
"username",
|
||||
"avatar",
|
||||
"discriminator",
|
||||
"public_flags",
|
||||
"flags",
|
||||
"locale",
|
||||
"mfa_enabled",
|
||||
"premium_type",
|
||||
"email",
|
||||
"verified",
|
||||
'id',
|
||||
'user_id',
|
||||
'username',
|
||||
'avatar',
|
||||
'discriminator',
|
||||
'public_flags',
|
||||
'flags',
|
||||
'locale',
|
||||
'mfa_enabled',
|
||||
'premium_type',
|
||||
'email',
|
||||
'verified',
|
||||
];
|
||||
|
||||
public $incrementing = false;
|
||||
|
@ -30,14 +30,16 @@ class DiscordUser extends Model
|
|||
/**
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function user(){
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getAvatar(){
|
||||
return "https://cdn.discordapp.com/avatars/" . $this->id . "/" . $this->avatar . ".png";
|
||||
public function getAvatar()
|
||||
{
|
||||
return 'https://cdn.discordapp.com/avatars/'.$this->id.'/'.$this->avatar.'.png';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,8 +61,8 @@ class Egg extends Model
|
|||
$array['environment'] = json_encode([$environment]);
|
||||
|
||||
self::query()->updateOrCreate([
|
||||
'id' => $array['id']
|
||||
], array_diff_key($array, array_flip(["id"]))
|
||||
'id' => $array['id'],
|
||||
], array_diff_key($array, array_flip(['id']))
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -72,8 +72,9 @@ class Egg extends Model
|
|||
|
||||
/**
|
||||
* @description remove eggs that have been deleted on pterodactyl
|
||||
* @param Nest $nest
|
||||
* @param array $eggs
|
||||
*
|
||||
* @param Nest $nest
|
||||
* @param array $eggs
|
||||
*/
|
||||
private static function removeDeletedEggs(Nest $nest, array $eggs): void
|
||||
{
|
||||
|
@ -82,7 +83,9 @@ class Egg extends Model
|
|||
}, $eggs);
|
||||
|
||||
$nest->eggs()->each(function (Egg $egg) use ($ids) {
|
||||
if (!in_array($egg->id, $ids)) $egg->delete();
|
||||
if (! in_array($egg->id, $ids)) {
|
||||
$egg->delete();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ class Invoice extends Model
|
|||
protected $fillable = [
|
||||
'invoice_name',
|
||||
'invoice_user',
|
||||
'payment_id'
|
||||
'payment_id',
|
||||
];
|
||||
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ class Location extends Model
|
|||
|
||||
/**
|
||||
* Sync locations with pterodactyl panel
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function syncLocations()
|
||||
|
@ -36,21 +37,21 @@ class Location extends Model
|
|||
|
||||
//map response
|
||||
$locations = array_map(function ($val) {
|
||||
return array(
|
||||
'id' => $val['attributes']['id'],
|
||||
'name' => $val['attributes']['short'],
|
||||
'description' => $val['attributes']['long']
|
||||
);
|
||||
return [
|
||||
'id' => $val['attributes']['id'],
|
||||
'name' => $val['attributes']['short'],
|
||||
'description' => $val['attributes']['long'],
|
||||
];
|
||||
}, $locations);
|
||||
|
||||
//update or create
|
||||
foreach ($locations as $location) {
|
||||
self::query()->updateOrCreate(
|
||||
[
|
||||
'id' => $location['id']
|
||||
'id' => $location['id'],
|
||||
],
|
||||
[
|
||||
'name' => $location['name'],
|
||||
'name' => $location['name'],
|
||||
'description' => $location['name'],
|
||||
]
|
||||
);
|
||||
|
@ -61,7 +62,8 @@ class Location extends Model
|
|||
|
||||
/**
|
||||
* @description remove locations that have been deleted on pterodactyl
|
||||
* @param array $locations
|
||||
*
|
||||
* @param array $locations
|
||||
*/
|
||||
private static function removeDeletedLocation(array $locations): void
|
||||
{
|
||||
|
@ -70,7 +72,9 @@ class Location extends Model
|
|||
}, $locations);
|
||||
|
||||
self::all()->each(function (Location $location) use ($ids) {
|
||||
if (!in_array($location->id, $ids)) $location->delete();
|
||||
if (! in_array($location->id, $ids)) {
|
||||
$location->delete();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -78,5 +82,4 @@ class Location extends Model
|
|||
{
|
||||
return $this->hasMany(Node::class, 'location_id', 'id');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -36,20 +36,20 @@ class Nest extends Model
|
|||
|
||||
//map response
|
||||
$nests = array_map(function ($nest) {
|
||||
return array(
|
||||
'id' => $nest['attributes']['id'],
|
||||
'name' => $nest['attributes']['name'],
|
||||
return [
|
||||
'id' => $nest['attributes']['id'],
|
||||
'name' => $nest['attributes']['name'],
|
||||
'description' => $nest['attributes']['description'],
|
||||
);
|
||||
];
|
||||
}, $nests);
|
||||
|
||||
foreach ($nests as $nest) {
|
||||
self::query()->updateOrCreate([
|
||||
'id' => $nest['id']
|
||||
'id' => $nest['id'],
|
||||
], [
|
||||
'name' => $nest['name'],
|
||||
'name' => $nest['name'],
|
||||
'description' => $nest['description'],
|
||||
'disabled' => false
|
||||
'disabled' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,8 @@ class Nest extends Model
|
|||
|
||||
/**
|
||||
* @description remove nests that have been deleted on pterodactyl
|
||||
* @param array $nests
|
||||
*
|
||||
* @param array $nests
|
||||
*/
|
||||
private static function removeDeletedNests(array $nests): void
|
||||
{
|
||||
|
@ -67,7 +68,9 @@ class Nest extends Model
|
|||
}, $nests);
|
||||
|
||||
self::all()->each(function (Nest $nest) use ($ids) {
|
||||
if (!in_array($nest->id, $ids)) $nest->delete();
|
||||
if (! in_array($nest->id, $ids)) {
|
||||
$nest->delete();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@ class Node extends Model
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
|
@ -37,25 +36,25 @@ class Node extends Model
|
|||
|
||||
//map response
|
||||
$nodes = array_map(function ($node) {
|
||||
return array(
|
||||
'id' => $node['attributes']['id'],
|
||||
return [
|
||||
'id' => $node['attributes']['id'],
|
||||
'location_id' => $node['attributes']['location_id'],
|
||||
'name' => $node['attributes']['name'],
|
||||
'name' => $node['attributes']['name'],
|
||||
'description' => $node['attributes']['description'],
|
||||
);
|
||||
];
|
||||
}, $nodes);
|
||||
|
||||
//update or create
|
||||
foreach ($nodes as $node) {
|
||||
self::query()->updateOrCreate(
|
||||
[
|
||||
'id' => $node['id']
|
||||
'id' => $node['id'],
|
||||
],
|
||||
[
|
||||
'name' => $node['name'],
|
||||
'name' => $node['name'],
|
||||
'description' => $node['description'],
|
||||
'location_id' => $node['location_id'],
|
||||
'disabled' => false
|
||||
'disabled' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -64,7 +63,8 @@ class Node extends Model
|
|||
|
||||
/**
|
||||
* @description remove nodes that have been deleted on pterodactyl
|
||||
* @param array $nodes
|
||||
*
|
||||
* @param array $nodes
|
||||
*/
|
||||
private static function removeDeletedNodes(array $nodes): void
|
||||
{
|
||||
|
@ -73,7 +73,9 @@ class Node extends Model
|
|||
}, $nodes);
|
||||
|
||||
self::all()->each(function (Node $node) use ($ids) {
|
||||
if (!in_array($node->id, $ids)) $node->delete();
|
||||
if (! in_array($node->id, $ids)) {
|
||||
$node->delete();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
46
app/Models/PartnerDiscount.php
Normal file
46
app/Models/PartnerDiscount.php
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class PartnerDiscount extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'user_id',
|
||||
'partner_discount',
|
||||
'registered_user_discount',
|
||||
'referral_system_commission',
|
||||
];
|
||||
|
||||
public static function getDiscount(int $user_id = null)
|
||||
{
|
||||
if ($partnerDiscount = PartnerDiscount::where('user_id', $user_id ?? Auth::user()->id)->first()) {
|
||||
return $partnerDiscount->partner_discount;
|
||||
} elseif ($ref_user = DB::table('user_referrals')->where('registered_user_id', '=', $user_id ?? Auth::user()->id)->first()) {
|
||||
if ($partnerDiscount = PartnerDiscount::where('user_id', $ref_user->referral_id)->first()) {
|
||||
return $partnerDiscount->registered_user_discount;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static function getCommission($user_id)
|
||||
{
|
||||
if ($partnerDiscount = PartnerDiscount::where('user_id', $user_id)->first()) {
|
||||
if ($partnerDiscount->referral_system_commission >= 0) {
|
||||
return $partnerDiscount->referral_system_commission >= 0;
|
||||
}
|
||||
}
|
||||
|
||||
return config('SETTINGS::REFERRAL:PERCENTAGE');
|
||||
}
|
||||
}
|
|
@ -7,14 +7,13 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use NumberFormatter;
|
||||
use Spatie\Activitylog\Traits\LogsActivity;
|
||||
|
||||
class Payment extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use LogsActivity;
|
||||
|
||||
public $incrementing = false;
|
||||
protected $primaryKey = 'id';
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
|
@ -55,14 +54,14 @@ class Payment extends Model
|
|||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param string $locale
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param string $locale
|
||||
* @return float
|
||||
*/
|
||||
public function formatToCurrency($value, $locale = 'en_US')
|
||||
{
|
||||
$formatter = new NumberFormatter($locale, NumberFormatter::CURRENCY);
|
||||
|
||||
return $formatter->formatCurrency($value, $this->currency_code);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,14 +7,20 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Spatie\Activitylog\LogOptions;
|
||||
use Spatie\Activitylog\Traits\LogsActivity;
|
||||
|
||||
class Product extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use LogsActivity;
|
||||
|
||||
public function getActivitylogOptions(): LogOptions
|
||||
{
|
||||
return LogOptions::defaults()
|
||||
-> logOnlyDirty()
|
||||
-> logOnly(['*'])
|
||||
-> dontSubmitEmptyLogs();
|
||||
}
|
||||
public $incrementing = false;
|
||||
|
||||
protected $guarded = ['id'];
|
||||
|
@ -29,7 +35,7 @@ class Product extends Model
|
|||
$product->{$product->getKeyName()} = $client->generateId($size = 21);
|
||||
});
|
||||
|
||||
static::deleting(function(Product $product) {
|
||||
static::deleting(function (Product $product) {
|
||||
$product->nodes()->detach();
|
||||
$product->eggs()->detach();
|
||||
});
|
||||
|
@ -42,12 +48,12 @@ class Product extends Model
|
|||
|
||||
public function getDailyPrice()
|
||||
{
|
||||
return ($this->price / 30);
|
||||
return $this->price / 30;
|
||||
}
|
||||
|
||||
public function getWeeklyPrice()
|
||||
{
|
||||
return ($this->price / 4);
|
||||
return $this->price / 4;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -61,14 +67,16 @@ class Product extends Model
|
|||
/**
|
||||
* @return BelongsToMany
|
||||
*/
|
||||
public function eggs() {
|
||||
public function eggs()
|
||||
{
|
||||
return $this->belongsToMany(Egg::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsToMany
|
||||
*/
|
||||
public function nodes() {
|
||||
public function nodes()
|
||||
{
|
||||
return $this->belongsToMany(Node::class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,17 +11,23 @@ use Illuminate\Database\Eloquent\Model;
|
|||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
use Illuminate\Http\Client\Response;
|
||||
use Spatie\Activitylog\LogOptions;
|
||||
use Spatie\Activitylog\Traits\LogsActivity;
|
||||
|
||||
/**
|
||||
* Class Server
|
||||
* @package App\Models
|
||||
*/
|
||||
class Server extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use LogsActivity;
|
||||
|
||||
public function getActivitylogOptions(): LogOptions
|
||||
{
|
||||
return LogOptions::defaults()
|
||||
-> logOnlyDirty()
|
||||
-> logOnly(['*'])
|
||||
-> dontSubmitEmptyLogs();
|
||||
}
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
|
@ -41,24 +47,21 @@ class Server extends Model
|
|||
* @var string[]
|
||||
*/
|
||||
protected $fillable = [
|
||||
"name",
|
||||
"description",
|
||||
"suspended",
|
||||
"identifier",
|
||||
"product_id",
|
||||
"pterodactyl_id",
|
||||
'name',
|
||||
'description',
|
||||
'suspended',
|
||||
'identifier',
|
||||
'product_id',
|
||||
'pterodactyl_id',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
protected $dates = [
|
||||
'suspended'
|
||||
protected $casts = [
|
||||
'suspended' => 'datetime',
|
||||
];
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
@ -71,7 +74,7 @@ class Server extends Model
|
|||
|
||||
static::deleting(function (Server $server) {
|
||||
$response = Pterodactyl::client()->delete("/application/servers/{$server->pterodactyl_id}");
|
||||
if ($response->failed() && !is_null($server->pterodactyl_id)) {
|
||||
if ($response->failed() && ! is_null($server->pterodactyl_id)) {
|
||||
//only return error when it's not a 404 error
|
||||
if ($response['errors'][0]['status'] != '404') {
|
||||
throw new Exception($response['errors'][0]['code']);
|
||||
|
@ -85,10 +88,9 @@ class Server extends Model
|
|||
*/
|
||||
public function isSuspended()
|
||||
{
|
||||
return !is_null($this->suspended);
|
||||
return ! is_null($this->suspended);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return PromiseInterface|Response
|
||||
*/
|
||||
|
@ -98,7 +100,6 @@ class Server extends Model
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function suspend()
|
||||
|
@ -107,7 +108,7 @@ class Server extends Model
|
|||
|
||||
if ($response->successful()) {
|
||||
$this->update([
|
||||
'suspended' => now()
|
||||
'suspended' => now(),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -123,14 +124,13 @@ class Server extends Model
|
|||
|
||||
if ($response->successful()) {
|
||||
$this->update([
|
||||
'suspended' => null
|
||||
'suspended' => null,
|
||||
]);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return HasOne
|
||||
*/
|
||||
|
@ -146,5 +146,4 @@ class Server extends Model
|
|||
{
|
||||
return $this->belongsTo(User::class, 'user_id', 'id');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -31,19 +31,20 @@ class Settings extends Model
|
|||
parent::boot();
|
||||
|
||||
static::updated(function (Settings $settings) {
|
||||
Cache::forget(self::CACHE_TAG .':'. $settings->key);
|
||||
Cache::forget(self::CACHE_TAG.':'.$settings->key);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param string $key
|
||||
* @param $default
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getValueByKey(string $key, $default = null)
|
||||
{
|
||||
return Cache::rememberForever(self::CACHE_TAG .':'. $key, function () use ($default, $key) {
|
||||
return Cache::rememberForever(self::CACHE_TAG.':'.$key, function () use ($default, $key) {
|
||||
$settings = self::find($key);
|
||||
|
||||
return $settings ? $settings->value : $default;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -5,12 +5,19 @@ namespace App\Models;
|
|||
use Hidehalo\Nanoid\Client;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use NumberFormatter;
|
||||
use Spatie\Activitylog\LogOptions;
|
||||
use Spatie\Activitylog\Traits\LogsActivity;
|
||||
use App\Models\Configuration;
|
||||
|
||||
class ShopProduct extends Model
|
||||
{
|
||||
use LogsActivity;
|
||||
public function getActivitylogOptions(): LogOptions
|
||||
{
|
||||
return LogOptions::defaults()
|
||||
-> logOnlyDirty()
|
||||
-> logOnly(['*'])
|
||||
-> dontSubmitEmptyLogs();
|
||||
}
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
|
@ -20,13 +27,13 @@ class ShopProduct extends Model
|
|||
* @var string[]
|
||||
*/
|
||||
protected $fillable = [
|
||||
"type",
|
||||
"price",
|
||||
"description",
|
||||
"display",
|
||||
"currency_code",
|
||||
"quantity",
|
||||
"disabled",
|
||||
'type',
|
||||
'price',
|
||||
'description',
|
||||
'display',
|
||||
'currency_code',
|
||||
'quantity',
|
||||
'disabled',
|
||||
];
|
||||
|
||||
public static function boot()
|
||||
|
@ -41,14 +48,14 @@ class ShopProduct extends Model
|
|||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param string $locale
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param string $locale
|
||||
* @return float
|
||||
*/
|
||||
public function formatToCurrency($value, $locale = 'en_US')
|
||||
{
|
||||
$formatter = new NumberFormatter($locale, NumberFormatter::CURRENCY);
|
||||
|
||||
return $formatter->formatCurrency($value, $this->currency_code);
|
||||
}
|
||||
|
||||
|
@ -59,10 +66,16 @@ class ShopProduct extends Model
|
|||
*/
|
||||
public function getTaxPercent()
|
||||
{
|
||||
$tax = config("SETTINGS::PAYMENTS:SALES_TAX");
|
||||
$tax = config('SETTINGS::PAYMENTS:SALES_TAX');
|
||||
|
||||
return $tax < 0 ? 0 : $tax;
|
||||
}
|
||||
|
||||
public function getPriceAfterDiscount()
|
||||
{
|
||||
return number_format($this->price - ($this->price * PartnerDiscount::getDiscount() / 100), 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the tax as Number
|
||||
*
|
||||
|
@ -70,7 +83,7 @@ class ShopProduct extends Model
|
|||
*/
|
||||
public function getTaxValue()
|
||||
{
|
||||
return number_format($this->price * $this->getTaxPercent() / 100, 2);
|
||||
return number_format($this->getPriceAfterDiscount() * $this->getTaxPercent() / 100, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -80,6 +93,6 @@ class ShopProduct extends Model
|
|||
*/
|
||||
public function getTotalPrice()
|
||||
{
|
||||
return number_format($this->price + $this->getTaxValue(), 2);
|
||||
return number_format($this->getPriceAfterDiscount() + $this->getTaxValue(), 2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,19 +3,36 @@
|
|||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Spatie\Activitylog\LogOptions;
|
||||
use Spatie\Activitylog\Traits\LogsActivity;
|
||||
|
||||
class Ticket extends Model
|
||||
{
|
||||
use LogsActivity;
|
||||
|
||||
class Ticket extends Model {
|
||||
protected $fillable = [
|
||||
'user_id', 'ticketcategory_id', 'ticket_id', 'title', 'priority', 'message', 'status', 'server'
|
||||
'user_id', 'ticketcategory_id', 'ticket_id', 'title', 'priority', 'message', 'status', 'server',
|
||||
];
|
||||
public function getActivitylogOptions(): LogOptions
|
||||
{
|
||||
return LogOptions::defaults()
|
||||
-> logOnlyDirty()
|
||||
-> logOnly(['*'])
|
||||
-> dontSubmitEmptyLogs();
|
||||
}
|
||||
|
||||
public function ticketcategory(){
|
||||
return $this->belongsTo(TicketCategory::class);}
|
||||
public function ticketcategory()
|
||||
{
|
||||
return $this->belongsTo(TicketCategory::class);
|
||||
}
|
||||
|
||||
public function ticketcomments(){
|
||||
return $this->hasMany(TicketComment::class);}
|
||||
public function ticketcomments()
|
||||
{
|
||||
return $this->hasMany(TicketComment::class);
|
||||
}
|
||||
|
||||
public function user(){
|
||||
return $this->belongsTo(User::class);}
|
||||
}
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,14 +4,14 @@ namespace App\Models;
|
|||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class TicketBlacklist extends Model {
|
||||
class TicketBlacklist extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
'user_id', 'status', 'reason'
|
||||
'user_id', 'status', 'reason',
|
||||
];
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'user_id', 'id');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,10 +4,12 @@ namespace App\Models;
|
|||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class TicketCategory extends Model {
|
||||
class TicketCategory extends Model
|
||||
{
|
||||
protected $fillable = ['name'];
|
||||
|
||||
public function tickets(){
|
||||
return $this->hasMany(Ticket::class);}
|
||||
|
||||
public function tickets()
|
||||
{
|
||||
return $this->hasMany(Ticket::class,'ticketcategory_id');
|
||||
}
|
||||
}
|
||||
|
|
@ -4,18 +4,24 @@ namespace App\Models;
|
|||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class TicketComment extends Model {
|
||||
protected $fillable = [
|
||||
'ticket_id', 'user_id', 'ticketcomment'
|
||||
];
|
||||
class TicketComment extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
'ticket_id', 'user_id', 'ticketcomment',
|
||||
];
|
||||
|
||||
public function ticketcategory(){
|
||||
return $this->belongsTo(TicketCategory::class);}
|
||||
public function ticketcategory()
|
||||
{
|
||||
return $this->belongsTo(TicketCategory::class);
|
||||
}
|
||||
|
||||
public function ticket(){
|
||||
return $this->belongsTo(Ticket::class);}
|
||||
public function ticket()
|
||||
{
|
||||
return $this->belongsTo(Ticket::class);
|
||||
}
|
||||
|
||||
public function user(){
|
||||
return $this->belongsTo(User::class);}
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
}
|
||||
|
|
@ -15,6 +15,7 @@ class UsefulLink extends Model
|
|||
'icon',
|
||||
'title',
|
||||
'link',
|
||||
'description'
|
||||
'description',
|
||||
'position',
|
||||
];
|
||||
}
|
||||
|
|
|
@ -12,12 +12,12 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
|
|||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Spatie\Activitylog\LogOptions;
|
||||
use Spatie\Activitylog\Traits\CausesActivity;
|
||||
use Spatie\Activitylog\Traits\LogsActivity;
|
||||
|
||||
/**
|
||||
* Class User
|
||||
* @package App\Models
|
||||
*/
|
||||
class User extends Authenticatable implements MustVerifyEmail
|
||||
{
|
||||
|
@ -38,7 +38,7 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
'server_limit',
|
||||
'last_seen',
|
||||
'ip',
|
||||
'pterodactyl_id'
|
||||
'pterodactyl_id',
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -60,7 +60,8 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
'discord_verified_at',
|
||||
'avatar',
|
||||
'suspended',
|
||||
'referral_code'
|
||||
'referral_code',
|
||||
'email_verified_reward'
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -83,11 +84,9 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
'last_seen' => 'datetime',
|
||||
'credits' => 'float',
|
||||
'server_limit' => 'float',
|
||||
'email_verified_reward' => 'boolean'
|
||||
];
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
@ -97,29 +96,21 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
});
|
||||
|
||||
static::deleting(function (User $user) {
|
||||
$user->servers()->chunk(10, function ($servers) {
|
||||
foreach ($servers as $server) {
|
||||
$server->delete();
|
||||
}
|
||||
|
||||
|
||||
// delete every server the user owns without using chunks
|
||||
$user->servers()->each(function ($server) {
|
||||
$server->delete();
|
||||
});
|
||||
|
||||
$user->payments()->chunk(10, function ($payments) {
|
||||
foreach ($payments as $payment) {
|
||||
$payment->delete();
|
||||
}
|
||||
});
|
||||
$user->payments()->delete();
|
||||
|
||||
$user->tickets()->chunk(10, function ($tickets) {
|
||||
foreach ($tickets as $ticket) {
|
||||
$ticket->delete();
|
||||
}
|
||||
});
|
||||
$user->tickets()->delete();
|
||||
|
||||
$user->ticketBlackList()->delete();
|
||||
|
||||
$user->vouchers()->detach();
|
||||
|
||||
|
||||
$user->discordUser()->delete();
|
||||
|
||||
Pterodactyl::client()->delete("/application/users/{$user->pterodactyl_id}");
|
||||
|
@ -174,9 +165,6 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
return $this->hasOne(DiscordUser::class);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function sendEmailVerificationNotification()
|
||||
{
|
||||
$this->notify(new QueuedVerifyEmail);
|
||||
|
@ -199,7 +187,6 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function suspend()
|
||||
|
@ -209,7 +196,7 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
}
|
||||
|
||||
$this->update([
|
||||
'suspended' => true
|
||||
'suspended' => true,
|
||||
]);
|
||||
|
||||
return $this;
|
||||
|
@ -227,7 +214,7 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
}
|
||||
|
||||
$this->update([
|
||||
'suspended' => false
|
||||
'suspended' => false,
|
||||
]);
|
||||
|
||||
return $this;
|
||||
|
@ -246,18 +233,17 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
public function getAvatar()
|
||||
{
|
||||
//TODO loading the images to confirm they exist is causing to much load time. alternative has to be found :) maybe onerror tag on the <img tags>
|
||||
// if ($this->discordUser()->exists()) {
|
||||
// if(@getimagesize($this->discordUser->getAvatar())) {
|
||||
// $avatar = $this->discordUser->getAvatar();
|
||||
// } else {
|
||||
// $avatar = "https://www.gravatar.com/avatar/" . md5(strtolower(trim($this->email)));
|
||||
// }
|
||||
// } else {
|
||||
// $avatar = "https://www.gravatar.com/avatar/" . md5(strtolower(trim($this->email)));
|
||||
// }
|
||||
|
||||
return "https://www.gravatar.com/avatar/" . md5(strtolower(trim($this->email)));
|
||||
// if ($this->discordUser()->exists()) {
|
||||
// if(@getimagesize($this->discordUser->getAvatar())) {
|
||||
// $avatar = $this->discordUser->getAvatar();
|
||||
// } else {
|
||||
// $avatar = "https://www.gravatar.com/avatar/" . md5(strtolower(trim($this->email)));
|
||||
// }
|
||||
// } else {
|
||||
// $avatar = "https://www.gravatar.com/avatar/" . md5(strtolower(trim($this->email)));
|
||||
// }
|
||||
|
||||
return 'https://www.gravatar.com/avatar/' . md5(strtolower(trim($this->email)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -279,9 +265,14 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
public function getVerifiedStatus()
|
||||
{
|
||||
$status = '';
|
||||
if ($this->hasVerifiedEmail()) $status .= 'email ';
|
||||
if ($this->discordUser()->exists()) $status .= 'discord';
|
||||
if ($this->hasVerifiedEmail()) {
|
||||
$status .= 'email ';
|
||||
}
|
||||
if ($this->discordUser()->exists()) {
|
||||
$status .= 'discord';
|
||||
}
|
||||
$status = str_replace(' ', '/', $status);
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
|
@ -295,7 +286,15 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
public function reVerifyEmail()
|
||||
{
|
||||
$this->forceFill([
|
||||
'email_verified_at' => null,
|
||||
'email_verified_at' => null
|
||||
])->save();
|
||||
}
|
||||
|
||||
public function getActivitylogOptions(): LogOptions
|
||||
{
|
||||
return LogOptions::defaults()
|
||||
->logOnly(['role', 'name', 'server_limit', 'pterodactyl_id', 'email'])
|
||||
->logOnlyDirty()
|
||||
->dontSubmitEmptyLogs();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,16 +6,22 @@ use Exception;
|
|||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Spatie\Activitylog\LogOptions;
|
||||
use Spatie\Activitylog\Traits\LogsActivity;
|
||||
|
||||
/**
|
||||
* Class Voucher
|
||||
* @package App\Models
|
||||
*/
|
||||
class Voucher extends Model
|
||||
{
|
||||
use HasFactory, LogsActivity;
|
||||
|
||||
public function getActivitylogOptions(): LogOptions
|
||||
{
|
||||
return LogOptions::defaults()
|
||||
-> logOnlyDirty()
|
||||
-> logOnly(['*'])
|
||||
-> dontSubmitEmptyLogs();
|
||||
}
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
|
@ -27,19 +33,15 @@ class Voucher extends Model
|
|||
'expires_at',
|
||||
];
|
||||
|
||||
protected $dates = [
|
||||
'expires_at'
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = [
|
||||
'expires_at' => 'datetime',
|
||||
'credits' => 'float',
|
||||
'uses' => 'integer'
|
||||
];
|
||||
'uses' => 'integer', ];
|
||||
|
||||
protected $appends = ['used', 'status'];
|
||||
|
||||
|
@ -59,9 +61,6 @@ class Voucher extends Model
|
|||
return $this->getStatus();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
@ -84,17 +83,22 @@ class Voucher extends Model
|
|||
*/
|
||||
public function getStatus()
|
||||
{
|
||||
if ($this->users()->count() >= $this->uses) return 'USES_LIMIT_REACHED';
|
||||
if (!is_null($this->expires_at)) {
|
||||
if ($this->expires_at->isPast()) return __('EXPIRED');
|
||||
if ($this->users()->count() >= $this->uses) {
|
||||
return 'USES_LIMIT_REACHED';
|
||||
}
|
||||
if (! is_null($this->expires_at)) {
|
||||
if ($this->expires_at->isPast()) {
|
||||
return __('EXPIRED');
|
||||
}
|
||||
}
|
||||
|
||||
return __('VALID');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
* @param User $user
|
||||
* @return float
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function redeem(User $user)
|
||||
|
@ -111,7 +115,7 @@ class Voucher extends Model
|
|||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
* @param User $user
|
||||
* @return null
|
||||
*/
|
||||
private function logRedeem(User $user)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue