mirror of
https://github.com/VueFileManager/vuefilemanager.git
synced 2026-04-06 18:53:48 +00:00
Compare commits
1515 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
97060092ba | ||
|
|
3a73e4c792 | ||
|
|
2e798bd1ec | ||
|
|
94afb626eb | ||
|
|
428b4c87a3 | ||
|
|
c912166905 | ||
|
|
aa9731dd13 | ||
|
|
05f58e1468 | ||
|
|
7659cc7221 | ||
|
|
a4b18c26b5 | ||
|
|
317d7aefc3 | ||
|
|
17d4bcd888 | ||
|
|
8dd4cf2be6 | ||
|
|
d8789a4788 | ||
|
|
1d670fcb52 | ||
|
|
b9975de700 | ||
|
|
31218240ae | ||
|
|
36c5e51b4f | ||
|
|
d6e9d2bd4f | ||
|
|
971ae4160e | ||
|
|
63da860df5 | ||
|
|
ab65aa8859 | ||
|
|
6bd1ec96bd | ||
|
|
8bab827d81 | ||
|
|
1d91d9759e | ||
|
|
127f1dc4cf | ||
|
|
1e10ff32a8 | ||
|
|
aa30b519fa | ||
|
|
3c28da2613 | ||
|
|
e87e2ec4e3 | ||
|
|
f66982b3ec | ||
|
|
68dc04963d | ||
|
|
69a48e8925 | ||
|
|
c0e431b384 | ||
|
|
b8741439f5 | ||
|
|
70901a2df5 | ||
|
|
d2371e667f | ||
|
|
000b5459f9 | ||
|
|
ed17ed1a79 | ||
|
|
8c75166980 | ||
|
|
6472997cc1 | ||
|
|
209667f55e | ||
|
|
73c84075c5 | ||
|
|
5d7fed7de8 | ||
|
|
b6cf1e2799 | ||
|
|
acfbbd56ca | ||
|
|
b9a6bc05ff | ||
|
|
e3293f0b1a | ||
|
|
4eb901dae0 | ||
|
|
911f15d493 | ||
|
|
a43c799d59 | ||
|
|
e9824bb807 | ||
|
|
2c933c65a7 | ||
|
|
0b2d05a899 | ||
|
|
4e2ac2b890 | ||
|
|
6bd7456f2e | ||
|
|
bbd6df4175 | ||
|
|
70fe106e45 | ||
|
|
1331409920 | ||
|
|
01970af8de | ||
|
|
63a72d6fe4 | ||
|
|
9b5f8731d2 | ||
|
|
4250e58370 | ||
|
|
f9b762de43 | ||
|
|
67b9f7f4dc | ||
|
|
cf7e17e188 | ||
|
|
137021fcdc | ||
|
|
3d2e279afd | ||
|
|
4fc5ccd26d | ||
|
|
89e4ae6737 | ||
|
|
8b3f76d1d0 | ||
|
|
37cc94aeda | ||
|
|
664f8d8e53 | ||
|
|
b1fd046084 | ||
|
|
e8fb5b6865 | ||
|
|
9ed2eec092 | ||
|
|
257de10cc8 | ||
|
|
2e61cee49c | ||
|
|
aca289b5a6 | ||
|
|
0f42704980 | ||
|
|
4f9fb3991c | ||
|
|
f75c20e5a7 | ||
|
|
c2d53479e8 | ||
|
|
89689816ad | ||
|
|
ba58e76d3b | ||
|
|
12d7b3e92b | ||
|
|
c8ebb5db9f | ||
|
|
869dbd4797 | ||
|
|
4b8bd3be52 | ||
|
|
a4aa329bf4 | ||
|
|
97a807a5e5 | ||
|
|
92561d137d | ||
|
|
43368c7555 | ||
|
|
5e9e4142d0 | ||
|
|
7be7203b96 | ||
|
|
0adc0f4fcd | ||
|
|
110a22d317 | ||
|
|
68b4722668 | ||
|
|
612298ebec | ||
|
|
48492f87be | ||
|
|
01735b4e1f | ||
|
|
e769c33af6 | ||
|
|
b635a17644 | ||
|
|
954f0e3361 | ||
|
|
6a9fa9ceec | ||
|
|
20162ac366 | ||
|
|
0a9740a363 | ||
|
|
4b366747b6 | ||
|
|
c2595a0de4 | ||
|
|
6e8714aec5 | ||
|
|
5e86799a82 | ||
|
|
d586eb9d7e | ||
|
|
35d89e2be1 | ||
|
|
409ab8c03f | ||
|
|
8be0ae2a62 | ||
|
|
d43efad45e | ||
|
|
c86f93ac1e | ||
|
|
64b0dff8fb | ||
|
|
ca76463fab | ||
|
|
e4dd9de931 | ||
|
|
dc8e3c8141 | ||
|
|
97ef846a44 | ||
|
|
5b130d01af | ||
|
|
552e5e02c9 | ||
|
|
19e29e69e0 | ||
|
|
ad8793ce28 | ||
|
|
6c3e7801da | ||
|
|
50eb67ac79 | ||
|
|
cd5af37bfe | ||
|
|
338f8664b7 | ||
|
|
6a4bfa8bfe | ||
|
|
b439fc1070 | ||
|
|
8baa466782 | ||
|
|
8df7794484 | ||
|
|
e71810a9bb | ||
|
|
b37bbe38dc | ||
|
|
a051ab568d | ||
|
|
ab2c8b8371 | ||
|
|
b803c32b41 | ||
|
|
5d1d883fb1 | ||
|
|
e5f4bad9a9 | ||
|
|
fbc9eed30b | ||
|
|
7740e1673f | ||
|
|
9de6c65643 | ||
|
|
9a15f2ecd8 | ||
|
|
86090d5192 | ||
|
|
6ed2efcc4e | ||
|
|
85d4f535eb | ||
|
|
03d78937dc | ||
|
|
596fa5f95c | ||
|
|
8d1ee24c7a | ||
|
|
d71e598758 | ||
|
|
18ffb24941 | ||
|
|
f5879c0670 | ||
|
|
60a3c46ffe | ||
|
|
76b32f551f | ||
|
|
03d42bee51 | ||
|
|
e240ce7736 | ||
|
|
93dbaa081d | ||
|
|
eb48aa46e3 | ||
|
|
7bd1079ce9 | ||
|
|
ade6b05bd0 | ||
|
|
7e0913b363 | ||
|
|
736a809e83 | ||
|
|
4379daa079 | ||
|
|
9a11af3b39 | ||
|
|
4ae4e70fe4 | ||
|
|
657248aa43 | ||
|
|
b0f1bb46d7 | ||
|
|
490fe5a120 | ||
|
|
953e7892b7 | ||
|
|
34bd1d3a3c | ||
|
|
8035ea2b23 | ||
|
|
993dfc8fa1 | ||
|
|
3649b6b7cf | ||
|
|
23fdab0f68 | ||
|
|
736174fda7 | ||
|
|
4e9c40d7ed | ||
|
|
10d8b592ea | ||
|
|
9f783fcd95 | ||
|
|
d386f70be8 | ||
|
|
2c86c62d7f | ||
|
|
4e9e8c47c0 | ||
|
|
ba308fa70a | ||
|
|
e8a0c421e9 | ||
|
|
bf6bc17d7d | ||
|
|
80b2371868 | ||
|
|
3d9272b05e | ||
|
|
2fa73dc3d2 | ||
|
|
b219c00113 | ||
|
|
c1f775975d | ||
|
|
a3805b4bff | ||
|
|
be37f95404 | ||
|
|
086dab99cd | ||
|
|
2d4c7241ef | ||
|
|
d4199a796d | ||
|
|
e4d44fc5eb | ||
|
|
40b13acbb9 | ||
|
|
b1160a1327 | ||
|
|
9cfe6118a9 | ||
|
|
64dbcf287d | ||
|
|
bfe4c257a2 | ||
|
|
1615be340a | ||
|
|
2ce165dd65 | ||
|
|
c5bfd99df7 | ||
|
|
182451515c | ||
|
|
ff476251f5 | ||
|
|
ef9f654834 | ||
|
|
ab042cc4b3 | ||
|
|
3f8fc1c9ce | ||
|
|
dff804153e | ||
|
|
d362b37cd3 | ||
|
|
621f6770c5 | ||
|
|
d1d58711c5 | ||
|
|
36883d1c0d | ||
|
|
0ca67c2348 | ||
|
|
0fbb8fd8ee | ||
|
|
b0829c71e9 | ||
|
|
af3f08e728 | ||
|
|
32d4873715 | ||
|
|
b8a1390220 | ||
|
|
9d4d1ba9aa | ||
|
|
8c59501907 | ||
|
|
ed67927672 | ||
|
|
e604c8e4fd | ||
|
|
4ea76419db | ||
|
|
8d13d82af9 | ||
|
|
6ee142b58c | ||
|
|
5964bebad2 | ||
|
|
6a48beb793 | ||
|
|
bbd8e70c9d | ||
|
|
e232543ea4 | ||
|
|
62c6331845 | ||
|
|
43f2a43d6c | ||
|
|
c5810e962b | ||
|
|
d7d95e22ea | ||
|
|
8c1e59d81a | ||
|
|
3c1c6eb5b9 | ||
|
|
df05eb0433 | ||
|
|
bb1d775585 | ||
|
|
7f49ae011c | ||
|
|
a608678bb9 | ||
|
|
aa515b5450 | ||
|
|
87466e4596 | ||
|
|
3f01dd3f95 | ||
|
|
5531be6640 | ||
|
|
1d144d6c9e | ||
|
|
b043878eed | ||
|
|
a2d0b26b68 | ||
|
|
381a440c61 | ||
|
|
95efdc3993 | ||
|
|
dece343d8b | ||
|
|
5d15f3da51 | ||
|
|
42245317f4 | ||
|
|
73ef6e6c1f | ||
|
|
881facc867 | ||
|
|
98d9f3ab0d | ||
|
|
7564c01fa3 | ||
|
|
1ad8fbdd57 | ||
|
|
10f37e645b | ||
|
|
ca883a6f93 | ||
|
|
0d59fe5b8e | ||
|
|
fea2d839e7 | ||
|
|
0c334f5daf | ||
|
|
87bcd50e44 | ||
|
|
01588fa06b | ||
|
|
e8f59ef0a9 | ||
|
|
9c040cfe48 | ||
|
|
4b899d8f29 | ||
|
|
e8c3fd74b1 | ||
|
|
1d1e6823c7 | ||
|
|
bc197cbb5e | ||
|
|
9a6abbd6e8 | ||
|
|
60407f9dce | ||
|
|
9d955799d3 | ||
|
|
4bab179e17 | ||
|
|
aa5742dafa | ||
|
|
f6f4184fb2 | ||
|
|
f6ea18fce2 | ||
|
|
a544578b38 | ||
|
|
5fa205de27 | ||
|
|
806af9da5c | ||
|
|
dfeef6fdf8 | ||
|
|
d0b4b729c9 | ||
|
|
1c4b4c6279 | ||
|
|
556f6d0813 | ||
|
|
3f4263393e | ||
|
|
a51dece5ee | ||
|
|
a7db1a22d2 | ||
|
|
ee80f454fb | ||
|
|
2c4175b708 | ||
|
|
fe3fbe7db7 | ||
|
|
3c35ea9a4e | ||
|
|
f835c6a7c2 | ||
|
|
5e48af22a2 | ||
|
|
2bba6dc051 | ||
|
|
ab03b471f7 | ||
|
|
9e973b89ce | ||
|
|
0e45092795 | ||
|
|
c1ace2854f | ||
|
|
4e471cb077 | ||
|
|
ffa4f67cbd | ||
|
|
8e4fc55b23 | ||
|
|
ee516fd384 | ||
|
|
da27c47d7a | ||
|
|
28d99cce78 | ||
|
|
0905a0660c | ||
|
|
d02ca13197 | ||
|
|
9ae2d54a5e | ||
|
|
64e80d387b | ||
|
|
70d7f2f5bd | ||
|
|
4315cddcb2 | ||
|
|
26f7cdb80f | ||
|
|
8495ed5422 | ||
|
|
2a0b01e888 | ||
|
|
6ebf5dc3cb | ||
|
|
dd1f3b299d | ||
|
|
4e2155b75a | ||
|
|
c0ca83193f | ||
|
|
08175d4dba | ||
|
|
e6043e4530 | ||
|
|
bf62c007ac | ||
|
|
1cf50206cb | ||
|
|
9bc0ce3c3d | ||
|
|
2fa0b5cd77 | ||
|
|
241190104e | ||
|
|
23054c2257 | ||
|
|
1e4649eec2 | ||
|
|
81f227c5e7 | ||
|
|
5829eaacc4 | ||
|
|
e0e488860d | ||
|
|
2c90db8e04 | ||
|
|
0a30ca0b98 | ||
|
|
ae138bb4d4 | ||
|
|
ad5b741feb | ||
|
|
cad1a1680c | ||
|
|
0f6dd0304f | ||
|
|
2724fb1873 | ||
|
|
0f4b80ddac | ||
|
|
6155173d82 | ||
|
|
6ca2269c80 | ||
|
|
4b751a29c2 | ||
|
|
ff9198a03e | ||
|
|
0c0a2424b7 | ||
|
|
a3abfd670a | ||
|
|
90303458a0 | ||
|
|
3f0a69a062 | ||
|
|
a303ffffdc | ||
|
|
64d1883f53 | ||
|
|
071bdc1bcd | ||
|
|
30025271c2 | ||
|
|
8ae24a9a6e | ||
|
|
dee1614297 | ||
|
|
c2e4b50df5 | ||
|
|
2e80da830a | ||
|
|
c84850e8d2 | ||
|
|
6fd8ddf680 | ||
|
|
ab3a307dc1 | ||
|
|
c3a6f5d703 | ||
|
|
293eb679fa | ||
|
|
45dcdcce16 | ||
|
|
a589ee5f7a | ||
|
|
06b28aeee3 | ||
|
|
047b907c60 | ||
|
|
eb7b319ebd | ||
|
|
aef715e061 | ||
|
|
fdfb5f57d7 | ||
|
|
0501e3e3d5 | ||
|
|
efb0fc4734 | ||
|
|
f15c81d342 | ||
|
|
6feadfd188 | ||
|
|
ee67b8050d | ||
|
|
c3398f0da4 | ||
|
|
171ee5fa04 | ||
|
|
1107bf66af | ||
|
|
5be55b52bd | ||
|
|
6db8b0662a | ||
|
|
45a3b5415b | ||
|
|
394a7b6baf | ||
|
|
3fafc811fe | ||
|
|
5ee77da25f | ||
|
|
421388b360 | ||
|
|
8828432e4d | ||
|
|
820f0b3890 | ||
|
|
b897eaf482 | ||
|
|
da74a38605 | ||
|
|
00c6562719 | ||
|
|
4498461e70 | ||
|
|
948c7453a6 | ||
|
|
eb948f9000 | ||
|
|
3fd43936e7 | ||
|
|
03730b80c0 | ||
|
|
3867c9cd67 | ||
|
|
b5c00e98df | ||
|
|
9f5172da85 | ||
|
|
a6940379cb | ||
|
|
a9e4daed35 | ||
|
|
e7d9fca9c2 | ||
|
|
638a1a9a72 | ||
|
|
4df575f5e9 | ||
|
|
7b0f9a19de | ||
|
|
f04c057490 | ||
|
|
09774b1d48 | ||
|
|
81362fef2d | ||
|
|
58fae35085 | ||
|
|
21e184f373 | ||
|
|
38e86b4b8b | ||
|
|
6980c28c57 | ||
|
|
e794ef5c17 | ||
|
|
f8317e761b | ||
|
|
5a28eeef1e | ||
|
|
cad8c31422 | ||
|
|
78f69ca816 | ||
|
|
bb9280d050 | ||
|
|
b751429dc5 | ||
|
|
45a46bbc65 | ||
|
|
b38b532cbe | ||
|
|
5ae875233b | ||
|
|
2ca42f530b | ||
|
|
dcba1e8407 | ||
|
|
854ae6d8fd | ||
|
|
940a2de13d | ||
|
|
42c2ffc274 | ||
|
|
0c71329dee | ||
|
|
f74bb7cec5 | ||
|
|
d855739bf2 | ||
|
|
a2726ae2c5 | ||
|
|
0b3fc946bd | ||
|
|
d16d73680f | ||
|
|
438e930e06 | ||
|
|
737fb7f32f | ||
|
|
e22ae97a87 | ||
|
|
fb91c1883a | ||
|
|
3652c64738 | ||
|
|
3d32e8f7e0 | ||
|
|
995319cfe5 | ||
|
|
1085062d10 | ||
|
|
8b1a3f0476 | ||
|
|
630cefee41 | ||
|
|
5725753052 | ||
|
|
ec92295fbf | ||
|
|
87dbcbceb8 | ||
|
|
3677e51c8f | ||
|
|
4396965d4d | ||
|
|
4319533873 | ||
|
|
1c16f0001c | ||
|
|
1f48abae0f | ||
|
|
a7fd410a68 | ||
|
|
f5e45126db | ||
|
|
fc74682e62 | ||
|
|
26bf65af88 | ||
|
|
ba05cdde83 | ||
|
|
e2cfdd5345 | ||
|
|
6cb2a1bb9a | ||
|
|
aa28118d75 | ||
|
|
c2667ab481 | ||
|
|
03e4f98ad6 | ||
|
|
4fc61afc11 | ||
|
|
6b71eabfa2 | ||
|
|
bb4f66f159 | ||
|
|
7f33df62a5 | ||
|
|
e1de316774 | ||
|
|
34fcbdc55c | ||
|
|
24edb85b24 | ||
|
|
1342dfa20f | ||
|
|
5adf9bd2be | ||
|
|
ea59624091 | ||
|
|
89e886b40c | ||
|
|
09449539fa | ||
|
|
c711150793 | ||
|
|
509fb32c81 | ||
|
|
763e63db55 | ||
|
|
b456a562a0 | ||
|
|
148f5982a9 | ||
|
|
59414a1e31 | ||
|
|
ffebe7fecc | ||
|
|
2403f89ca3 | ||
|
|
97b429f8d1 | ||
|
|
ec83c0e018 | ||
|
|
51701214a2 | ||
|
|
7dd116a769 | ||
|
|
7e9e9ee25b | ||
|
|
662ba988a0 | ||
|
|
5c59296724 | ||
|
|
703a49711c | ||
|
|
1d0ba4d679 | ||
|
|
ceba8f5cc1 | ||
|
|
8eff3969d3 | ||
|
|
7b3bd1135c | ||
|
|
e77e0cda03 | ||
|
|
8d67d089bf | ||
|
|
d4220254db | ||
|
|
4fa93512b5 | ||
|
|
66de377657 | ||
|
|
6cf7e5d26d | ||
|
|
3b34dc43ce | ||
|
|
d498446911 | ||
|
|
4feba76f57 | ||
|
|
e1bb4b2cbe | ||
|
|
53a2950dd3 | ||
|
|
68563b9e10 | ||
|
|
1c188081b3 | ||
|
|
62cbcd14ed | ||
|
|
9dbc3ab969 | ||
|
|
ca48d430bb | ||
|
|
08139c8f96 | ||
|
|
5de2b8b0e0 | ||
|
|
26aa8b46df | ||
|
|
0d8f1b64a7 | ||
|
|
ead4f65e1a | ||
|
|
8a64fe070b | ||
|
|
f017be476f | ||
|
|
0b5fcfe676 | ||
|
|
a2e6a3bd2f | ||
|
|
e823e57c71 | ||
|
|
a113fffbf0 | ||
|
|
10c25cf9d5 | ||
|
|
6a957fa9fc | ||
|
|
5d2071ea91 | ||
|
|
e892e0e94f | ||
|
|
8b7a80e10d | ||
|
|
86dac75071 | ||
|
|
31ec9b4fda | ||
|
|
21b838eda4 | ||
|
|
e5e713659e | ||
|
|
8d53ed1531 | ||
|
|
05f6023053 | ||
|
|
29a954e21b | ||
|
|
ec29764c3f | ||
|
|
b4887cea0e | ||
|
|
c7c11fe5b9 | ||
|
|
49c6f25acb | ||
|
|
3b4085f0ca | ||
|
|
09d8b84870 | ||
|
|
9d189b3d12 | ||
|
|
2363592dcd | ||
|
|
22733619d1 | ||
|
|
4ab5e17068 | ||
|
|
50abdc3266 | ||
|
|
6f5b3c05ad | ||
|
|
aa8851aacb | ||
|
|
0cc3285ee9 | ||
|
|
6ec3c88690 | ||
|
|
88948af6d9 | ||
|
|
da69898051 | ||
|
|
47e834c368 | ||
|
|
0194e546fd | ||
|
|
f88ed999c5 | ||
|
|
606765561d | ||
|
|
b1cb7be678 | ||
|
|
6bb7789232 | ||
|
|
60b34e53a3 | ||
|
|
f5e182baf6 | ||
|
|
dc0dedffea | ||
|
|
56a5bfd483 | ||
|
|
534d474307 | ||
|
|
22ae148a22 | ||
|
|
e5a2be112b | ||
|
|
401b511b40 | ||
|
|
afb8323541 | ||
|
|
04e46b7fcb | ||
|
|
f37c4f62b7 | ||
|
|
27753f30ad | ||
|
|
b4dfbd1623 | ||
|
|
b368d56bbc | ||
|
|
6cb3503870 | ||
|
|
bb7831f717 | ||
|
|
43738bf8db | ||
|
|
d8a33703ab | ||
|
|
86eee2f533 | ||
|
|
342d07126a | ||
|
|
5439ba1aae | ||
|
|
42487d43f1 | ||
|
|
9275487cfa | ||
|
|
26f367031e | ||
|
|
e645eebc4d | ||
|
|
5382da0b1f | ||
|
|
c6b4a767da | ||
|
|
78a6cf0c92 | ||
|
|
9e4de3657e | ||
|
|
2d0a166ad7 | ||
|
|
17a40ea808 | ||
|
|
0179dcb068 | ||
|
|
7d685fa166 | ||
|
|
8242ba860f | ||
|
|
dd3e477593 | ||
|
|
b08662b307 | ||
|
|
de047f7dd8 | ||
|
|
ca257ae113 | ||
|
|
c7c81dda34 | ||
|
|
e5322d6c2e | ||
|
|
067c123aa8 | ||
|
|
751ebcb7eb | ||
|
|
69e167a337 | ||
|
|
7f0d00017f | ||
|
|
d80fa81f36 | ||
|
|
fa3cb93b19 | ||
|
|
5d4486a4ad | ||
|
|
8456aaf01e | ||
|
|
459087337c | ||
|
|
5626a054da | ||
|
|
64e8bccb31 | ||
|
|
16823b9566 | ||
|
|
13287ce6b0 | ||
|
|
7f6598238e | ||
|
|
3bfca2ac83 | ||
|
|
03ddb61d33 | ||
|
|
d8f1f396d5 | ||
|
|
936af4497b | ||
|
|
2fb3cff98b | ||
|
|
4e069b98f6 | ||
|
|
9503ecbd79 | ||
|
|
f71a31ab78 | ||
|
|
be04715f8b | ||
|
|
8ff3b408cc | ||
|
|
b447d2ea83 | ||
|
|
7fe576ba26 | ||
|
|
913bdf70ad | ||
|
|
f711ec7d89 | ||
|
|
946dfa7d99 | ||
|
|
c5aadd3c6e | ||
|
|
884c36a5a3 | ||
|
|
b6c77a6685 | ||
|
|
21d75678c0 | ||
|
|
78541c1c3c | ||
|
|
0ad8afcfe2 | ||
|
|
d958da933d | ||
|
|
d039700b90 | ||
|
|
4ea46f5e81 | ||
|
|
88234d5748 | ||
|
|
6dd40df7d5 | ||
|
|
79281e80f6 | ||
|
|
67bbc79f20 | ||
|
|
d798f06d36 | ||
|
|
9cece789a0 | ||
|
|
054c0eb32c | ||
|
|
a2e0c1810d | ||
|
|
d16a37f2ed | ||
|
|
0a4d5dea8a | ||
|
|
8faa865fb7 | ||
|
|
6ca84d9041 | ||
|
|
4851fb5eab | ||
|
|
7c5cb79677 | ||
|
|
496a6ea5a7 | ||
|
|
f402141bfb | ||
|
|
34eaf3e411 | ||
|
|
6514102df2 | ||
|
|
c7dab4b268 | ||
|
|
8387467ee7 | ||
|
|
9744344146 | ||
|
|
a5b8744082 | ||
|
|
eb22f25b07 | ||
|
|
0cc39f8575 | ||
|
|
9d52da4e3a | ||
|
|
18ff8a6dc7 | ||
|
|
1f5f0a7fbb | ||
|
|
73cd950054 | ||
|
|
5c12334d92 | ||
|
|
8b5e5fecfb | ||
|
|
77d14a9d80 | ||
|
|
02582f2ae3 | ||
|
|
d600ee7830 | ||
|
|
8d8fdbf9ba | ||
|
|
de9d91da62 | ||
|
|
29cb889283 | ||
|
|
ee86fbbe66 | ||
|
|
aec5b98313 | ||
|
|
5a9f2985c9 | ||
|
|
cdaad931bb | ||
|
|
98823504ba | ||
|
|
6203581893 | ||
|
|
f139dbae08 | ||
|
|
dc8ec5f20b | ||
|
|
9b2dbe06c7 | ||
|
|
23602f5e4f | ||
|
|
b232701783 | ||
|
|
54167ae366 | ||
|
|
ffbf809b1e | ||
|
|
bf4d860bb8 | ||
|
|
4e86e7dd4b | ||
|
|
60a2a88805 | ||
|
|
e6133d6071 | ||
|
|
1e515ede88 | ||
|
|
57506fc34f | ||
|
|
06bb51989e | ||
|
|
b1a6fc3bf2 | ||
|
|
351d57b103 | ||
|
|
2d7b6e4e05 | ||
|
|
ce846cc076 | ||
|
|
0f08d9fe38 | ||
|
|
d018dcba06 | ||
|
|
ceb1e5c9dd | ||
|
|
b53d9fb93a | ||
|
|
240880e2ad | ||
|
|
3dfee77042 | ||
|
|
9c26c764bd | ||
|
|
407f2d2874 | ||
|
|
cd44274690 | ||
|
|
265cc393e1 | ||
|
|
21d6410f76 | ||
|
|
e3ddf27023 | ||
|
|
15e154176d | ||
|
|
6ef50978d5 | ||
|
|
54af098148 | ||
|
|
fda82d6dbf | ||
|
|
d4990d8d5f | ||
|
|
524791f251 | ||
|
|
b45662942d | ||
|
|
3f93373f60 | ||
|
|
018b973c0f | ||
|
|
133dd5285d | ||
|
|
3ec5166936 | ||
|
|
69fccfeaad | ||
|
|
c9631a9727 | ||
|
|
841c1db54a | ||
|
|
705281325f | ||
|
|
cea881ce38 | ||
|
|
3fee035e9e | ||
|
|
2aac3fc966 | ||
|
|
07b249346b | ||
|
|
37cad85a86 | ||
|
|
19cc01131b | ||
|
|
d40108f6a9 | ||
|
|
f715cd897f | ||
|
|
a9556896ca | ||
|
|
1db153aeef | ||
|
|
6f9b6835a7 | ||
|
|
d1cb1a378b | ||
|
|
c916916a4d | ||
|
|
a3516769de | ||
|
|
f44e262d6e | ||
|
|
ac62a432fe | ||
|
|
2bfdf5c311 | ||
|
|
e751a6bc90 | ||
|
|
eb38ca8c9a | ||
|
|
4304fb1ddb | ||
|
|
7984ce3ef1 | ||
|
|
d299183ecd | ||
|
|
174f2a2c1f | ||
|
|
e0e060e5a1 | ||
|
|
5c6a873b02 | ||
|
|
f5f2179145 | ||
|
|
bee7352b28 | ||
|
|
7020720392 | ||
|
|
8282defbe3 | ||
|
|
49c147f609 | ||
|
|
dfa82535eb | ||
|
|
bcfe813e1e | ||
|
|
78bf913d92 | ||
|
|
0c6621494e | ||
|
|
e0ecfce382 | ||
|
|
80a86bbddd | ||
|
|
60f0f3c329 | ||
|
|
d53a4964ae | ||
|
|
ca1d037975 | ||
|
|
fdd9c5a591 | ||
|
|
d4e3957598 | ||
|
|
f24d57d88d | ||
|
|
fd313e3d83 | ||
|
|
527a0790e3 | ||
|
|
42210233dc | ||
|
|
cc0436b8f3 | ||
|
|
a926545146 | ||
|
|
26e3194f21 | ||
|
|
882b5543f0 | ||
|
|
1f529ae7e0 | ||
|
|
a6e60d2efa | ||
|
|
d71dbea246 | ||
|
|
5ac786fb4c | ||
|
|
8cf6b6ea78 | ||
|
|
a99cbc2841 | ||
|
|
b23259309c | ||
|
|
b5a8fe8b1a | ||
|
|
c697f8a451 | ||
|
|
fb6dfbe7b4 | ||
|
|
15fba236d7 | ||
|
|
99e9c0086e | ||
|
|
c57a244ae1 | ||
|
|
e13a2cd18f | ||
|
|
58b7e6d584 | ||
|
|
1d569f13c2 | ||
|
|
a521f88859 | ||
|
|
a824e4d78e | ||
|
|
3d491c7e58 | ||
|
|
52842c61e5 | ||
|
|
4e3e63ba00 | ||
|
|
0c7a416cb5 | ||
|
|
63b4aa0e1d | ||
|
|
09dfaaa34a | ||
|
|
a4231ea30a | ||
|
|
387c824647 | ||
|
|
ec2a10e32f | ||
|
|
34a1f31f96 | ||
|
|
20b26ce57d | ||
|
|
717f28608f | ||
|
|
dc60ba972f | ||
|
|
98688b81c0 | ||
|
|
843a1bc690 | ||
|
|
8b360edb2b | ||
|
|
1175724e43 | ||
|
|
79295e77b6 | ||
|
|
f78cedbc0c | ||
|
|
cea889d912 | ||
|
|
98691dcdd4 | ||
|
|
6a6e05f035 | ||
|
|
60337934cb | ||
|
|
9a80c044fc | ||
|
|
5341fbedc6 | ||
|
|
53f667372d | ||
|
|
cd39606905 | ||
|
|
2d6f375c8b | ||
|
|
46dcdc5e94 | ||
|
|
79826a3601 | ||
|
|
826e90c087 | ||
|
|
087b6e77cc | ||
|
|
94f30e5c9f | ||
|
|
1f1f646f62 | ||
|
|
0ea7447901 | ||
|
|
1b893d59ea | ||
|
|
6a805b03fa | ||
|
|
71a1eb8e7c | ||
|
|
3823fb22d9 | ||
|
|
8810880616 | ||
|
|
cb496281b7 | ||
|
|
a65ec6e8c7 | ||
|
|
7576904587 | ||
|
|
f8cb879e42 | ||
|
|
5f4fa23a68 | ||
|
|
c2771be913 | ||
|
|
7a85a03fea | ||
|
|
5c848f75a6 | ||
|
|
7b65d868c4 | ||
|
|
35fefdc383 | ||
|
|
32d54fa50e | ||
|
|
be2690fd1c | ||
|
|
eaec744356 | ||
|
|
8951ebc69f | ||
|
|
c38ecb412b | ||
|
|
d190eeb46d | ||
|
|
03fc533848 | ||
|
|
7cb485fb43 | ||
|
|
fffede1c10 | ||
|
|
093c9451ec | ||
|
|
69eb8dacce | ||
|
|
b0e8bfa3ce | ||
|
|
5167f082f7 | ||
|
|
6d8a7a429c | ||
|
|
54f1f4c9a8 | ||
|
|
91cb795054 | ||
|
|
9fb9b8a1b0 | ||
|
|
d55f5c3b41 | ||
|
|
91fc7f2d9d | ||
|
|
3860faf851 | ||
|
|
76e1cd1113 | ||
|
|
dccf98602d | ||
|
|
e0eaf5cede | ||
|
|
58d8724cea | ||
|
|
1534696e0d | ||
|
|
b659f2ad8d | ||
|
|
2333b52d68 | ||
|
|
b0859f71cd | ||
|
|
2d814f3839 | ||
|
|
8b250e94cb | ||
|
|
0633131a73 | ||
|
|
dc98c839a2 | ||
|
|
0232a7abeb | ||
|
|
cde8b6aae3 | ||
|
|
8c493395c4 | ||
|
|
2e52af5275 | ||
|
|
20a6404d8d | ||
|
|
d6db2f3a7c | ||
|
|
29d1b68dd5 | ||
|
|
54dc57fcbf | ||
|
|
8f77a497b5 | ||
|
|
a1778eab52 | ||
|
|
18150cd920 | ||
|
|
5046071f3a | ||
|
|
fc952d089b | ||
|
|
79e2dfc502 | ||
|
|
c14aefd5ea | ||
|
|
a9a572c434 | ||
|
|
ddf88304ff | ||
|
|
aeb5c8419a | ||
|
|
49d8b5abd9 | ||
|
|
4384e50f34 | ||
|
|
90efc51359 | ||
|
|
ec6d11b7ae | ||
|
|
9ba3d9a6ba | ||
|
|
66cca02b36 | ||
|
|
c1d9622879 | ||
|
|
840bdc3878 | ||
|
|
460b95e6de | ||
|
|
a438f8fb99 | ||
|
|
097a930245 | ||
|
|
40866405fc | ||
|
|
d90af84311 | ||
|
|
cdd99f66b7 | ||
|
|
36cea4853f | ||
|
|
d05e9bf43e | ||
|
|
8ac41837b2 | ||
|
|
157427c750 | ||
|
|
e7cfa07392 | ||
|
|
82019f4833 | ||
|
|
838a412823 | ||
|
|
16eb105f03 | ||
|
|
14eaf6da4e | ||
|
|
7d28e09042 | ||
|
|
5215d7d38d | ||
|
|
dd271ea8cc | ||
|
|
6397ce9a67 | ||
|
|
8568a815a0 | ||
|
|
6fc29eac8e | ||
|
|
449724e78a | ||
|
|
e5de408ab0 | ||
|
|
1c057e9f86 | ||
|
|
f6f9199b87 | ||
|
|
cb99e105c0 | ||
|
|
24676e2392 | ||
|
|
c0da1b0b07 | ||
|
|
d7b8214406 | ||
|
|
3fc11b781b | ||
|
|
f2be4059cf | ||
|
|
edfcf8e1bd | ||
|
|
081a69450a | ||
|
|
b50e0041e0 | ||
|
|
847221d385 | ||
|
|
2bba4f961a | ||
|
|
359ae80e22 | ||
|
|
dd489d48ba | ||
|
|
9189d73df9 | ||
|
|
6456950081 | ||
|
|
0df72b1803 | ||
|
|
904e2d705f | ||
|
|
4d078dc24a | ||
|
|
a7e26cb61f | ||
|
|
fd7a23225c | ||
|
|
0139cc92bf | ||
|
|
7cefc8dfa1 | ||
|
|
0000909ec0 | ||
|
|
61824a511c | ||
|
|
cb239fb3bc | ||
|
|
08099b9671 | ||
|
|
bb8a205b7e | ||
|
|
09dda32dfd | ||
|
|
790052804e | ||
|
|
2e233990a2 | ||
|
|
8a1c20bf4a | ||
|
|
6dc34964d8 | ||
|
|
d8bbfcd4d2 | ||
|
|
26f23863c0 | ||
|
|
32bc3bacc0 | ||
|
|
688f234ae1 | ||
|
|
6e330046b3 | ||
|
|
438ddbb868 | ||
|
|
bcd4209aca | ||
|
|
88ac70bc67 | ||
|
|
b31fb4f7d2 | ||
|
|
862fc68134 | ||
|
|
a04c2de84f | ||
|
|
6ac8089cd7 | ||
|
|
f29a2571df | ||
|
|
c0d1fa6965 | ||
|
|
499e4e8f7c | ||
|
|
e9a1ad9f09 | ||
|
|
dccf006f1e | ||
|
|
a2e467b65d | ||
|
|
3d876835f6 | ||
|
|
5e0007764e | ||
|
|
21142c1171 | ||
|
|
50bdac62dc | ||
|
|
ac75cb5d0f | ||
|
|
1ba685c484 | ||
|
|
8b3c6cfc27 | ||
|
|
f252a0ba23 | ||
|
|
3c8d6ac862 | ||
|
|
bd881da856 | ||
|
|
86b6844d62 | ||
|
|
da38580504 | ||
|
|
9fbd5fd472 | ||
|
|
6b43464e85 | ||
|
|
8c6e0321fd | ||
|
|
25d9691a31 | ||
|
|
6052174b83 | ||
|
|
583d65a1da | ||
|
|
856d3b6aa1 | ||
|
|
33a65b1c77 | ||
|
|
4613c72412 | ||
|
|
04fa824d16 | ||
|
|
75e51c3f10 | ||
|
|
ca7944b17a | ||
|
|
23c0e8b0f7 | ||
|
|
7d020b0bbc | ||
|
|
93e5a29d40 | ||
|
|
3ee8c255d5 | ||
|
|
7e50e221f2 | ||
|
|
6f6c987538 | ||
|
|
5dcf8df751 | ||
|
|
b895cbc9c0 | ||
|
|
321e62fb0a | ||
|
|
e9aca0a6c3 | ||
|
|
717dcb02ef | ||
|
|
9744780022 | ||
|
|
c47886fb8b | ||
|
|
e103e61617 | ||
|
|
e65ccf0680 | ||
|
|
85613dd846 | ||
|
|
b52fe0454b | ||
|
|
3645b3e8f7 | ||
|
|
01e94b97ba | ||
|
|
2e906daf58 | ||
|
|
25a28c37c8 | ||
|
|
7e8511ab3f | ||
|
|
7cd29fce98 | ||
|
|
b0c81a692c | ||
|
|
b71072ddda | ||
|
|
79d3e2beac | ||
|
|
fc11a38457 | ||
|
|
be6ccecee6 | ||
|
|
66198a50e1 | ||
|
|
0910daa1a3 | ||
|
|
397b3228d0 | ||
|
|
2a02716a53 | ||
|
|
b105c9fc8f | ||
|
|
9105ce8bb1 | ||
|
|
6056e97463 | ||
|
|
639f24fdfd | ||
|
|
110f7b60d6 | ||
|
|
a7ba0719a5 | ||
|
|
213d6230ca | ||
|
|
eba8903792 | ||
|
|
16b7575fca | ||
|
|
14efc4c29f | ||
|
|
da49a7b051 | ||
|
|
469e0883d9 | ||
|
|
3e18dbd4f9 | ||
|
|
1568eab905 | ||
|
|
452da6c6b4 | ||
|
|
d5e371f8d6 | ||
|
|
b6290a0cad | ||
|
|
afd2270e0e | ||
|
|
58ecc33986 | ||
|
|
2598ba38db | ||
|
|
30ae2c0a54 | ||
|
|
87b3625b27 | ||
|
|
bf9581173c | ||
|
|
e40ddbec14 | ||
|
|
131ae8109f | ||
|
|
90c0466cd0 | ||
|
|
f531ffce11 | ||
|
|
13992deb41 | ||
|
|
b2d133e5a3 | ||
|
|
26085c475f | ||
|
|
7772ef6b40 | ||
|
|
5130082111 | ||
|
|
a8fa3694be | ||
|
|
6ac6528243 | ||
|
|
ec51440c3a | ||
|
|
cdb395c77f | ||
|
|
ee4a2205f6 | ||
|
|
0f357ace50 | ||
|
|
4d5cd3d80f | ||
|
|
bb3f4d4bda | ||
|
|
9fef371099 | ||
|
|
9e330da7a6 | ||
|
|
254a00e18e | ||
|
|
ac6b2b09e1 | ||
|
|
a18ceb1b4f | ||
|
|
f2c44c3cfe | ||
|
|
ffe6de5b98 | ||
|
|
4a114ec096 | ||
|
|
0e3c6e286e | ||
|
|
09d2032a70 | ||
|
|
4142f829be | ||
|
|
6f7b34dd0a | ||
|
|
c6b3995cc3 | ||
|
|
19925e398f | ||
|
|
c722c50ec3 | ||
|
|
4163c28e37 | ||
|
|
80f27d7448 | ||
|
|
df5d5cb75f | ||
|
|
5910bb1206 | ||
|
|
61635db3db | ||
|
|
4999b23474 | ||
|
|
a90311593b | ||
|
|
cff7cd6b32 | ||
|
|
c8dedd44c4 | ||
|
|
2e9112d110 | ||
|
|
aa51484303 | ||
|
|
19a75d2fb1 | ||
|
|
f4b3f1f163 | ||
|
|
ed8ab2978f | ||
|
|
db9900fcfb | ||
|
|
ba7d6be249 | ||
|
|
816c8c3e07 | ||
|
|
c73e44ff01 | ||
|
|
fc18280842 | ||
|
|
1d52186f17 | ||
|
|
87e05d9521 | ||
|
|
ce477fdaf1 | ||
|
|
617f715774 | ||
|
|
2c69553582 | ||
|
|
f142919cd1 | ||
|
|
f0e9c80572 | ||
|
|
adbe35e8b5 | ||
|
|
f3783e6f98 | ||
|
|
1bb59854ea | ||
|
|
803cc089bd | ||
|
|
ba902a30b3 | ||
|
|
6b67f861c3 | ||
|
|
749bc4ae83 | ||
|
|
7e3bbe4008 | ||
|
|
cb272709a3 | ||
|
|
961a8900be | ||
|
|
732fc48aa4 | ||
|
|
07cc977684 | ||
|
|
380a588b0a | ||
|
|
9297eae1d7 | ||
|
|
419a1d8180 | ||
|
|
9cc9111d63 | ||
|
|
0364e73c60 | ||
|
|
bb469f2520 | ||
|
|
d0bd866354 | ||
|
|
c5e9d29362 | ||
|
|
71d0005193 | ||
|
|
95eb167622 | ||
|
|
5778de20f2 | ||
|
|
9c3c044623 | ||
|
|
deaac3717c | ||
|
|
353180491b | ||
|
|
b022cde9e0 | ||
|
|
b837cc1906 | ||
|
|
89a6c51672 | ||
|
|
bb2094016b | ||
|
|
3e8acd9b4b | ||
|
|
db57bde4fc | ||
|
|
8ef5444136 | ||
|
|
af5181d4d7 | ||
|
|
6075a1b7c8 | ||
|
|
266f9d8a0a | ||
|
|
ed90173ec9 | ||
|
|
ff4af2978d | ||
|
|
5e37e10a0c | ||
|
|
cc526f8d95 | ||
|
|
8de3e80c4f | ||
|
|
2c7cb67e7c | ||
|
|
9606d0e7db | ||
|
|
8be86183fa | ||
|
|
1126a45524 | ||
|
|
8a4ffd03c6 | ||
|
|
8d85aad601 | ||
|
|
1045423692 | ||
|
|
aecdf56304 | ||
|
|
e164d1021c | ||
|
|
33fa77cd73 | ||
|
|
891ca7260b | ||
|
|
9f1174b547 | ||
|
|
1f615c54af | ||
|
|
6b909c2380 | ||
|
|
5660fcd4dc | ||
|
|
da7aee2790 | ||
|
|
dd4fab8e7c | ||
|
|
88540bd2a6 | ||
|
|
355b016f22 | ||
|
|
485dddec68 | ||
|
|
4c947a0e4d | ||
|
|
842abcb6b1 | ||
|
|
b87f8b68d4 | ||
|
|
ce08240355 | ||
|
|
e514994b08 | ||
|
|
779b7fc8ba | ||
|
|
5844e66b7f | ||
|
|
2782dc879b | ||
|
|
80f38d47ed | ||
|
|
350b3cb6b3 | ||
|
|
b544aa875f | ||
|
|
9c7d7a336b | ||
|
|
9b91fe3d59 | ||
|
|
d4df26bf35 | ||
|
|
7e4bd191d7 | ||
|
|
0add1eaf7f | ||
|
|
69b72d24a9 | ||
|
|
b1c15bb6a7 | ||
|
|
b38f04533c | ||
|
|
cd9d1d91bd | ||
|
|
7f21755f5a | ||
|
|
f95b3acbd2 | ||
|
|
0748f8face | ||
|
|
617ba2a6a8 | ||
|
|
4e098286a6 | ||
|
|
1536af7a5b | ||
|
|
33d6d1cd60 | ||
|
|
63ba4d3a1d | ||
|
|
4ab716bf9c | ||
|
|
594a4acc94 | ||
|
|
42d243e2fe | ||
|
|
9583c22b72 | ||
|
|
b66d47bf2b | ||
|
|
bcba0fd057 | ||
|
|
1784ff84c8 | ||
|
|
2007279a69 | ||
|
|
d8b279479a | ||
|
|
bb2e349a31 | ||
|
|
674290edfc | ||
|
|
486d8de378 | ||
|
|
b82f34ed4d | ||
|
|
81dc7d7ed7 | ||
|
|
a2d3bdd67b | ||
|
|
fdef2de99d | ||
|
|
f55472442f | ||
|
|
3328fdebb0 | ||
|
|
97ade6c238 | ||
|
|
5225673163 | ||
|
|
27675d7f38 | ||
|
|
92962aac17 | ||
|
|
f38b265ba7 | ||
|
|
6736afaefb | ||
|
|
dfb809acee | ||
|
|
5227a5fb99 | ||
|
|
fe728479d0 | ||
|
|
b7e1be7518 | ||
|
|
1359b78d21 | ||
|
|
920ee19651 | ||
|
|
7dd4e65d77 | ||
|
|
fd02fbfe08 | ||
|
|
00e515e995 | ||
|
|
55ba82442a | ||
|
|
7a963cf5b3 | ||
|
|
2f332197e6 | ||
|
|
ac38d35ae1 | ||
|
|
af1a8e6333 | ||
|
|
18518106ca | ||
|
|
92e02d8b57 | ||
|
|
b42d480c91 | ||
|
|
c8a9f18265 | ||
|
|
56b7f30d47 | ||
|
|
725a34b7d0 | ||
|
|
595bce60eb | ||
|
|
bf6cd34cf6 | ||
|
|
b8790a964b | ||
|
|
9a1a9ee206 | ||
|
|
05f850ab2c | ||
|
|
c2868c051d | ||
|
|
28b39a79e6 | ||
|
|
2dbd9dd62d | ||
|
|
9dbce7a73a | ||
|
|
8ac5c8fd38 | ||
|
|
2a105877f3 | ||
|
|
28efba5773 | ||
|
|
60f02622da | ||
|
|
7eee7deba5 | ||
|
|
ba0b2bd3b9 | ||
|
|
86090b5870 | ||
|
|
39681bc48a | ||
|
|
96e1bdd99f | ||
|
|
eebeee6948 | ||
|
|
67cf7a6ced | ||
|
|
7be02edead | ||
|
|
d65c27091c | ||
|
|
6c3630085e | ||
|
|
f6dbb5e71e | ||
|
|
29fce75d35 | ||
|
|
a80e4364ae | ||
|
|
bfb3888555 | ||
|
|
5e408267ee | ||
|
|
a4725df5f7 | ||
|
|
dee562c56e | ||
|
|
e1016502a1 | ||
|
|
541924448b | ||
|
|
18b97866f2 | ||
|
|
6f2278b908 | ||
|
|
bdd8d63162 | ||
|
|
8ca7881c5e | ||
|
|
8d04a94dbc | ||
|
|
d92bb50a03 | ||
|
|
44158c74e3 | ||
|
|
847bcec22f | ||
|
|
e984ae6beb | ||
|
|
e2a52d27f5 | ||
|
|
9c92cffde3 | ||
|
|
ce20452f38 | ||
|
|
6c888c6bd3 | ||
|
|
2b2d9a0764 | ||
|
|
ed2d008f4b | ||
|
|
9972f471c4 | ||
|
|
03ef16d90d | ||
|
|
4158d4f31e | ||
|
|
e65acd8a4f | ||
|
|
ba5e05f77a | ||
|
|
82cf82e4b5 | ||
|
|
f5e19e47f7 | ||
|
|
43b1aa7f89 | ||
|
|
0e1ebdd809 | ||
|
|
6e3adcd459 | ||
|
|
9c147165e1 | ||
|
|
689b064756 | ||
|
|
6b32ae9795 | ||
|
|
267556b39d | ||
|
|
eb2e39cd32 | ||
|
|
58ae75ecc9 | ||
|
|
a5dd0e0d30 | ||
|
|
cec2450940 | ||
|
|
fdd8f16384 | ||
|
|
2112fe879b | ||
|
|
078d920c19 | ||
|
|
98d1926ab3 | ||
|
|
2263cc9511 | ||
|
|
9a736a2615 | ||
|
|
4b1e5fcb46 | ||
|
|
a0c39bd955 | ||
|
|
973b301a46 | ||
|
|
e0f192777f | ||
|
|
ce1bad57cd | ||
|
|
77b126b85a | ||
|
|
3adf57a6b1 | ||
|
|
cc72e4e3a2 | ||
|
|
3285af3603 | ||
|
|
a8457cf261 | ||
|
|
04990fcf7b | ||
|
|
ba28ac6184 | ||
|
|
a100671cc0 | ||
|
|
ded02fc15b | ||
|
|
64fd6a2265 | ||
|
|
c2a5d4bc74 | ||
|
|
fed95cbd64 | ||
|
|
e60bbb369a | ||
|
|
7379d17a40 | ||
|
|
26e0535407 | ||
|
|
0f8a89bbad | ||
|
|
2f89f6303a | ||
|
|
4b3ca7e34b | ||
|
|
2c0cf43802 | ||
|
|
d255b01c70 | ||
|
|
6a9edc49c0 | ||
|
|
96faf2de0e | ||
|
|
5a2e6a5e53 | ||
|
|
c509eeceb1 | ||
|
|
299292a817 | ||
|
|
b11bd0e521 | ||
|
|
8fb859b441 | ||
|
|
28a5f58b80 | ||
|
|
7da4d1f64b | ||
|
|
07086c7550 | ||
|
|
5246c47c86 | ||
|
|
2975d1555d | ||
|
|
bd946be0b0 | ||
|
|
e6ff90f6fc | ||
|
|
08dc813af9 | ||
|
|
9098634b99 | ||
|
|
00213824f1 | ||
|
|
65624326c7 | ||
|
|
e92d9344b9 | ||
|
|
55cf58fffd | ||
|
|
a3c43af7ba | ||
|
|
a10d394abb | ||
|
|
b16f22b0eb | ||
|
|
5bc66d51be | ||
|
|
7b27fa70d8 | ||
|
|
372b3aa407 | ||
|
|
bda293bc53 | ||
|
|
11873d06ff | ||
|
|
89ea50b893 | ||
|
|
874b4bb768 | ||
|
|
1e49f52abe | ||
|
|
94088e76ec | ||
|
|
c7abcce729 | ||
|
|
e9d2f4bacc | ||
|
|
7e7965f98e | ||
|
|
d823ae687b | ||
|
|
21a36c0965 | ||
|
|
c3d162b991 | ||
|
|
7e325c5101 | ||
|
|
59ff07fb01 | ||
|
|
2ba92ed3b6 | ||
|
|
418c072414 | ||
|
|
397fe6b7e4 | ||
|
|
97d500028a | ||
|
|
527dfeef9f | ||
|
|
1b3baab691 | ||
|
|
5d512f7806 | ||
|
|
0da525f692 | ||
|
|
d076817c9e | ||
|
|
d2af7c1f5e | ||
|
|
ef002f9186 | ||
|
|
f1006355c4 | ||
|
|
ec6087a03c | ||
|
|
2e465f4d03 | ||
|
|
08bf6654fc | ||
|
|
77e29852a5 | ||
|
|
6bc84d4b25 | ||
|
|
d31e2ab98b | ||
|
|
ee14c34671 | ||
|
|
a8b290692e | ||
|
|
441f911560 | ||
|
|
10090b474a | ||
|
|
aff2594ef2 | ||
|
|
66aad7c488 | ||
|
|
896be9c9c9 | ||
|
|
8d1821e05d | ||
|
|
b7014552d2 | ||
|
|
8561556f5c | ||
|
|
58f7479380 | ||
|
|
7b70c81d4d | ||
|
|
1981f39f9e | ||
|
|
e86ea3e5c4 | ||
|
|
8e01b837a2 | ||
|
|
f33fe84350 | ||
|
|
dbbad817c7 | ||
|
|
0eb0939598 | ||
|
|
65f7855703 | ||
|
|
45d482d347 | ||
|
|
1654dc8678 | ||
|
|
cb417ea76d | ||
|
|
17df4aea35 | ||
|
|
714429d8f4 | ||
|
|
0df03f1d32 | ||
|
|
fefc10afb8 | ||
|
|
1658627069 | ||
|
|
16ab540298 | ||
|
|
4e5afa4747 | ||
|
|
d76ff07bf4 | ||
|
|
b38333bb64 | ||
|
|
f863537190 | ||
|
|
a72a672aaf | ||
|
|
a3dd817e7a | ||
|
|
9d9e07d0fa | ||
|
|
30783d0e5d | ||
|
|
3a296f0f9c | ||
|
|
c0d5a771a5 | ||
|
|
8fc7272e38 | ||
|
|
8b8dc34ba6 | ||
|
|
966145d384 | ||
|
|
2b4060cb7b | ||
|
|
9455a361dc | ||
|
|
26132e23a3 | ||
|
|
5acaadeaae | ||
|
|
324f4b1ffa | ||
|
|
0c02952f7a | ||
|
|
f76a4b37e4 | ||
|
|
f33f93006e | ||
|
|
382756a6f0 | ||
|
|
559bee6ca2 | ||
|
|
190fc651ae | ||
|
|
1c62da4e7c | ||
|
|
8a9d2d7f9a | ||
|
|
ae3be12934 | ||
|
|
4683e0d084 | ||
|
|
c55d3f5350 | ||
|
|
7273d60154 | ||
|
|
587daa5ffe | ||
|
|
064e635d35 | ||
|
|
06db522545 | ||
|
|
e5335c2472 | ||
|
|
a2ec066c6d | ||
|
|
15d4ffc349 | ||
|
|
9af9e45b8a | ||
|
|
f30dd38b96 | ||
|
|
d5f3599b9e | ||
|
|
de62ab535c | ||
|
|
8b8562916b | ||
|
|
0d7b920cbe | ||
|
|
f3254a380f | ||
|
|
0e12029efc | ||
|
|
fd6aa5c6b2 | ||
|
|
5be9db83f7 | ||
|
|
12d6b0bf57 | ||
|
|
961462fe54 | ||
|
|
f0e0103d81 | ||
|
|
755523e07b | ||
|
|
c4ace0697b | ||
|
|
69489c4ee2 | ||
|
|
e05d7468b5 | ||
|
|
1a6a91335e | ||
|
|
80de069c7b | ||
|
|
2de8bbe548 | ||
|
|
7ba2a3bec1 | ||
|
|
89fa2fce23 | ||
|
|
84b47416d6 | ||
|
|
55c72cddba | ||
|
|
6effd4a7d9 | ||
|
|
95f6695d00 | ||
|
|
fde7f0f73b | ||
|
|
dd1bffec09 | ||
|
|
83a951b3af | ||
|
|
6762ed25dc | ||
|
|
6ba869234e | ||
|
|
2c04376a61 | ||
|
|
f180f1fff8 | ||
|
|
ab65ca7a13 | ||
|
|
8895b5062a | ||
|
|
2f4aafb1b3 | ||
|
|
be08c8487a | ||
|
|
0d5df91d2d | ||
|
|
72e4067beb | ||
|
|
ba4f888826 | ||
|
|
82b43eb996 | ||
|
|
777132ec40 | ||
|
|
7f6f60227a | ||
|
|
ab6ff5dbfd | ||
|
|
0d272bc9b7 | ||
|
|
2b08d7801b | ||
|
|
cec4ff6cda | ||
|
|
6f300ba1d5 | ||
|
|
86813629ed | ||
|
|
aac0aa755f | ||
|
|
4be77c07ac | ||
|
|
9372906a3e | ||
|
|
e12e521622 | ||
|
|
0082c3a6a8 | ||
|
|
f79973e922 | ||
|
|
59ca45e9b1 | ||
|
|
bb22ec1e88 | ||
|
|
ba315014fa | ||
|
|
8387f56048 | ||
|
|
68acf5f986 | ||
|
|
785dade6b2 |
108
.env.example
108
.env.example
@@ -1,14 +1,16 @@
|
||||
APP_NAME=VueFileManager
|
||||
APP_ENV=production
|
||||
APP_KEY=base64:sB1YuKsbWv7MdWugb9ZsYBqv2QZJ+QOuHZHEddOsUuo=
|
||||
APP_ENV=local
|
||||
APP_KEY=base64:sC1YuKsbWv7MdWugb9ZsYBqv2QZJ+QOuHZHEddOsAao=
|
||||
APP_DEBUG=true
|
||||
APP_URL=http://localhost
|
||||
APP_DEMO=false
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
LOG_CHANNEL=daily
|
||||
|
||||
SCOUT_DRIVER=tntsearch
|
||||
FILESYSTEM_DRIVER=
|
||||
CHUNK_SIZE=128
|
||||
SCOUT_QUEUE=true
|
||||
|
||||
FILESYSTEM_DISK=local
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
@@ -17,9 +19,11 @@ DB_DATABASE=laravel
|
||||
DB_USERNAME=root
|
||||
DB_PASSWORD=
|
||||
|
||||
BROADCAST_DRIVER=log
|
||||
DB_MYSQLDUMP_PATH=/usr/bin
|
||||
|
||||
BROADCAST_DRIVER=null
|
||||
CACHE_DRIVER=file
|
||||
QUEUE_CONNECTION=sync
|
||||
QUEUE_CONNECTION=database
|
||||
SESSION_DRIVER=file
|
||||
SESSION_LIFETIME=120
|
||||
|
||||
@@ -27,46 +31,76 @@ REDIS_HOST=127.0.0.1
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
|
||||
MAIL_DRIVER=
|
||||
MAIL_DRIVER=log
|
||||
MAIL_HOST=
|
||||
MAIL_PORT=
|
||||
MAIL_USERNAME=
|
||||
MAIL_USERNAME=example@domain.com
|
||||
MAIL_PASSWORD=
|
||||
MAIL_ENCRYPTION=
|
||||
MAIL_FROM_ADDRESS="${MAIL_USERNAME}"
|
||||
MAIL_FROM_NAME="${MAIL_USERNAME}"
|
||||
|
||||
POSTMARK_TOKEN=
|
||||
|
||||
MAILGUN_DOMAIN=
|
||||
MAILGUN_SECRET=
|
||||
MAILGUN_ENDPOINT=
|
||||
|
||||
AWS_ACCESS_KEY_ID=
|
||||
AWS_SECRET_ACCESS_KEY=
|
||||
AWS_DEFAULT_REGION=
|
||||
AWS_BUCKET=
|
||||
AWS_SESSION_TOKEN=
|
||||
|
||||
DO_SPACES_KEY=
|
||||
DO_SPACES_SECRET=
|
||||
DO_SPACES_ENDPOINT=
|
||||
DO_SPACES_REGION=
|
||||
DO_SPACES_BUCKET=
|
||||
S3_ACCESS_KEY_ID=
|
||||
S3_SECRET_ACCESS_KEY=
|
||||
S3_DEFAULT_REGION=
|
||||
S3_BUCKET=
|
||||
S3_URL=
|
||||
|
||||
WASABI_KEY=
|
||||
WASABI_SECRET=
|
||||
WASABI_ENDPOINT=
|
||||
WASABI_REGION=
|
||||
WASABI_BUCKET=
|
||||
|
||||
BACKBLAZE_KEY=
|
||||
BACKBLAZE_SECRET=
|
||||
BACKBLAZE_ENDPOINT=
|
||||
BACKBLAZE_REGION=
|
||||
BACKBLAZE_BUCKET=
|
||||
|
||||
PASSPORT_CLIENT_ID=
|
||||
PASSPORT_CLIENT_SECRET=
|
||||
|
||||
APP_DEPLOY_SECRET=
|
||||
|
||||
CASHIER_LOGGER=stack
|
||||
CASHIER_CURRENCY=
|
||||
STRIPE_KEY=
|
||||
STRIPE_SECRET=
|
||||
STRIPE_SECRET_KEY=
|
||||
STRIPE_PUBLIC_KEY=
|
||||
STRIPE_WEBHOOK_SECRET=
|
||||
CASHIER_PAYMENT_NOTIFICATION=App\Notifications\ConfirmPayment
|
||||
|
||||
PAYSTACK_SECRET=
|
||||
PAYSTACK_PUBLIC_KEY=
|
||||
|
||||
PAYPAL_CLIENT_ID=
|
||||
PAYPAL_CLIENT_SECRET=
|
||||
PAYPAL_WEBHOOK_ID=
|
||||
PAYPAL_IS_LIVE=false
|
||||
|
||||
FACEBOOK_CLIENT_ID=
|
||||
FACEBOOK_CLIENT_SECRET=
|
||||
|
||||
GOOGLE_CLIENT_ID=
|
||||
GOOGLE_CLIENT_SECRET=
|
||||
|
||||
GITHUB_CLIENT_ID=
|
||||
GITHUB_CLIENT_SECRET=
|
||||
|
||||
RECAPTCHA_CLIENT_ID=
|
||||
RECAPTCHA_CLIENT_SECRET=
|
||||
|
||||
SANCTUM_STATEFUL_DOMAINS=localhost,localhost:8000,127.0.0.1,127.0.0.1:8000,::1
|
||||
|
||||
PUSHER_APP_ID=local
|
||||
PUSHER_APP_KEY=local
|
||||
PUSHER_APP_SECRET=local
|
||||
PUSHER_APP_CLUSTER=mt1
|
||||
PUSHER_APP_HOST=
|
||||
PUSHER_APP_PORT=
|
||||
PUSHER_APP_TLS=true
|
||||
PUSHER_APP_ALLOWED_ORIGIN=
|
||||
|
||||
IS_ADMIN_VUEFILEMANAGER_BAR=true
|
||||
IS_SETUP_WIZARD_DEMO=false
|
||||
IS_SETUP_WIZARD_DEBUG=false
|
||||
|
||||
FTP_HOST=
|
||||
FTP_USERNAME=
|
||||
FTP_PASSWORD=
|
||||
|
||||
AZURE_STORAGE_NAME=
|
||||
AZURE_STORAGE_KEY=
|
||||
AZURE_STORAGE_CONTAINER=
|
||||
AZURE_STORAGE_URL=
|
||||
45
.env.testing
Normal file
45
.env.testing
Normal file
@@ -0,0 +1,45 @@
|
||||
APP_NAME=Laravel
|
||||
APP_ENV=local
|
||||
APP_KEY=base64:DZMmPFCbaykO5HNb9ltj1PKX/WKGylZf0s/ghUWUCGs=
|
||||
APP_DEBUG=true
|
||||
APP_URL=http://localhost
|
||||
APP_DEMO=false
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
|
||||
DB_CONNECTION=sqlite
|
||||
DB_HOST=null
|
||||
DB_PORT=null
|
||||
DB_DATABASE=database/test.sqlite
|
||||
DB_USERNAME=null
|
||||
DB_PASSWORD=null
|
||||
|
||||
FILESYSTEM_DISK=local
|
||||
BROADCAST_DRIVER=null
|
||||
CACHE_DRIVER=file
|
||||
SESSION_DRIVER=file
|
||||
SESSION_LIFETIME=120
|
||||
SCOUT_DRIVER=tntsearch
|
||||
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
|
||||
MAIL_MAILER=log
|
||||
MAIL_HOST=smtp.mailtrap.io
|
||||
MAIL_PORT=2525
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
MAIL_FROM_ADDRESS=null
|
||||
MAIL_FROM_NAME="${APP_NAME}"
|
||||
|
||||
S3_ACCESS_KEY_ID=
|
||||
S3_SECRET_ACCESS_KEY=
|
||||
S3_DEFAULT_REGION=us-east-1
|
||||
S3_BUCKET=
|
||||
|
||||
SANCTUM_STATEFUL_DOMAINS=localhost,127.0.0.1,127.0.0.1:8000,::1
|
||||
|
||||
|
||||
DB_MYSQLDUMP_PATH="/usr/bin"
|
||||
29
.github/workflows/backend-code-style-fix.yml
vendored
Normal file
29
.github/workflows/backend-code-style-fix.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
name: Code Style Fix
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
php-cs-fixer:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.head_ref }}
|
||||
|
||||
- name: Run PHP CS Fixer
|
||||
uses: docker://oskarstark/php-cs-fixer-ga
|
||||
with:
|
||||
args: --config=.php-cs-fixer.dist.php --allow-risky=yes
|
||||
|
||||
- name: Commit changes
|
||||
uses: stefanzweifel/git-auto-commit-action@v4
|
||||
with:
|
||||
commit_message: Fix backend code styling
|
||||
35
.github/workflows/build.yml
vendored
Normal file
35
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
name: Frontend Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [14.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install
|
||||
|
||||
- run: npm run prod
|
||||
|
||||
- name: Commit changes
|
||||
uses: stefanzweifel/git-auto-commit-action@v4
|
||||
with:
|
||||
commit_message: Application Build
|
||||
43
.github/workflows/unit-testing.yml
vendored
Normal file
43
.github/workflows/unit-testing.yml
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
name: Unit Testing
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
php: [8.0]
|
||||
stability: [prefer-stable]
|
||||
|
||||
name: P${{ matrix.php }} - ${{ matrix.stability }} - ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
extensions: ctype, json, exif, dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick, fileinfo
|
||||
coverage: none
|
||||
|
||||
- name: Setup problem matchers
|
||||
run: |
|
||||
echo "::add-matcher::${{ runner.tool_cache }}/php.json"
|
||||
echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
|
||||
|
||||
- name: Install dependencies
|
||||
run: composer update --${{ matrix.stability }} --prefer-dist --no-interaction
|
||||
|
||||
- name: Run tests
|
||||
run: vendor/bin/phpunit
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -9,10 +9,15 @@
|
||||
.idea
|
||||
.env
|
||||
.env.backup
|
||||
.env.testing
|
||||
.php-cs-fixer.cache
|
||||
.phpunit.result.cache
|
||||
.phpstorm.meta.php
|
||||
.vscode/
|
||||
_ide_helper.php
|
||||
Homestead.json
|
||||
Homestead.yaml
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
prettier.json
|
||||
/public/temp
|
||||
|
||||
80
.php-cs-fixer.dist.php
Normal file
80
.php-cs-fixer.dist.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
$finder = PhpCsFixer\Finder::create()
|
||||
->in([
|
||||
__DIR__ . '/src',
|
||||
__DIR__ . '/routes',
|
||||
__DIR__ . '/config',
|
||||
__DIR__ . '/tests',
|
||||
])
|
||||
->name('*.php')
|
||||
->notName('*.blade.php')
|
||||
->ignoreDotFiles(true)
|
||||
->ignoreVCS(true);
|
||||
|
||||
$config = new PhpCsFixer\Config();
|
||||
|
||||
return $config->setRules([
|
||||
'@PSR2' => true,
|
||||
'nullable_type_declaration_for_default_null_value' => [
|
||||
'use_nullable_type_declaration' => true
|
||||
],
|
||||
'array_syntax' => [
|
||||
'syntax' => 'short'
|
||||
],
|
||||
'ordered_imports' => [
|
||||
'sort_algorithm' => 'length'
|
||||
],
|
||||
'blank_line_before_statement' => [
|
||||
'statements' => ['break', 'case', 'continue', 'declare', 'default', 'do', 'exit', 'for', 'foreach', 'goto', 'if', 'include', 'include_once', 'require', 'require_once', 'return', 'switch', 'throw', 'try', 'while', 'yield', 'yield_from'],
|
||||
],
|
||||
'method_argument_space' => [
|
||||
'on_multiline' => 'ensure_fully_multiline',
|
||||
'keep_multiple_spaces_after_comma' => true,
|
||||
],
|
||||
'no_extra_blank_lines' => [
|
||||
'tokens' => ['break', 'case', 'continue', 'curly_brace_block', 'default', 'extra', 'parenthesis_brace_block', 'return', 'square_brace_block', 'switch', 'throw', 'use', 'use_trait'],
|
||||
],
|
||||
'cast_spaces' => [
|
||||
'space' => 'single'
|
||||
],
|
||||
'use_arrow_functions' => true,
|
||||
'phpdoc_single_line_var_spacing' => true,
|
||||
'phpdoc_var_without_name' => true,
|
||||
'single_space_after_construct' => true,
|
||||
'single_line_after_imports' => true,
|
||||
'no_unused_imports' => true,
|
||||
'not_operator_with_successor_space' => true,
|
||||
'trailing_comma_in_multiline' => ['elements' => ['arrays']],
|
||||
'phpdoc_scalar' => true,
|
||||
'unary_operator_spaces' => true,
|
||||
'binary_operator_spaces' => ['operators' => ['=>' => 'align']],
|
||||
'single_trait_insert_per_statement' => false,
|
||||
'method_chaining_indentation' => true,
|
||||
'array_indentation' => true,
|
||||
'single_quote' => true,
|
||||
'no_singleline_whitespace_before_semicolons' => true,
|
||||
'no_empty_statement' => true,
|
||||
'standardize_increment' => true,
|
||||
'object_operator_without_whitespace' => true,
|
||||
'ternary_operator_spaces' => true,
|
||||
'no_leading_namespace_whitespace' => true,
|
||||
'no_blank_lines_before_namespace' => true,
|
||||
'blank_line_after_namespace' => true,
|
||||
'fully_qualified_strict_types' => true,
|
||||
'single_line_throw' => true,
|
||||
'function_typehint_space' => true,
|
||||
'simplified_if_return' => true,
|
||||
'no_useless_else' => true,
|
||||
'no_unneeded_curly_braces' => true,
|
||||
'no_empty_comment' => true,
|
||||
'no_blank_lines_after_class_opening' => true,
|
||||
'whitespace_after_comma_in_array' => true,
|
||||
'trim_array_spaces' => true,
|
||||
'no_whitespace_before_comma_in_array' => true,
|
||||
'constant_case' => true,
|
||||
'lowercase_keywords' => true,
|
||||
'lowercase_static_reference' => true,
|
||||
'lambda_not_used_import' => true,
|
||||
])
|
||||
->setFinder($finder);
|
||||
1
.php_cs.cache
Normal file
1
.php_cs.cache
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
5
.prettierrc.yaml
Normal file
5
.prettierrc.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
trailingComma: "es5"
|
||||
tabWidth: 4
|
||||
semi: false
|
||||
singleQuote: true
|
||||
printWidth: 120
|
||||
449
README.md
449
README.md
@@ -1,63 +1,52 @@
|
||||
|
||||

|
||||
# Private Cloud Storage Build on Laravel & Vue.js
|
||||
|
||||
## Supporting VueFileManager
|
||||
Hi, we are trying make the best experience with VueFileManager. There is a lot things to do, and a lot of features we can make.
|
||||
|
||||
But, it can't be done without you, development is more and more complicated and we have to hire new colleagues to help with it. There is couple way you can support us, and then, we support you with all great new features which can be. Thanks you for participating on this awesome software!
|
||||
|
||||
- [Buy me a Coffe](https://www.buymeacoffee.com/pepe)
|
||||
- [One-time donation via PayPal](https://www.paypal.me/peterpapp)
|
||||
- [Become a backer or sponsor on Patreon](https://www.patreon.com/vuefilemanager)
|
||||
- [Purchase Licence on CodeCanyon](https://codecanyon.net/item/vue-file-manager-with-laravel-backend/25815986)
|
||||
# Private Cloud Storage Build by Laravel & Vue.js
|
||||
|
||||
## Contents
|
||||
|
||||
- [Installation](#installation)
|
||||
- [Server Requirements](#server-requirements)
|
||||
- [Installation](#installation)
|
||||
- [PHP Configuration](#php-configuration)
|
||||
- [Chunk Upload](#chunk-upload)
|
||||
- [Nginx Configuration](#nginx-configuration)
|
||||
- [Apache Configuration](#apache-configuration)
|
||||
- [Recover Failed Installation](#installation-failed)
|
||||
- [Update Guide](#update-guide)
|
||||
- [Instructions](#instructions)
|
||||
- [Update from 1.7.x to 1.7.7](#update-from-17x-to-177)
|
||||
- [Update from 1.6.x to 1.7](#update-from-16x-to-17)
|
||||
- [Payments](#payments)
|
||||
- [Get your active plans](#get-your-active-plans)
|
||||
- [Manage Failed Payments](#manage-failed-payments)
|
||||
- [Tax Rates](#tax-rates)
|
||||
- [Server Requirements](#server-requirements)
|
||||
- [Installation](#installation)
|
||||
- [Updating Application](#updating-application)
|
||||
- [Nginx Configuration](#nginx-configuration)
|
||||
- [Apache Configuration](#apache-configuration)
|
||||
- [Migrating to Another Domain](#migrating-to-another-domain)
|
||||
- [Social Authentication](#social-authentication)
|
||||
- [Subscription Configuration](#subscription-configuration)
|
||||
- [Configuring Production/Testing Environment](#configuring-productiontesting-environment)
|
||||
- [Upgrading From Testing Environment to the Production Mode](#upgrading-from-testing-environment-to-the-production-mode)
|
||||
- [Broadcasting](#broadcasting)
|
||||
- [About Broadcasting](#about-broadcasting)
|
||||
- [Install Broadcast Server](#install-broadcast-server)
|
||||
- [Developers](#developers)
|
||||
- [Running development environment on your localhost](#running-development-environment-on-your-localhost)
|
||||
- [Supported Storages](#supported-storages)
|
||||
- [How to Create New Language](#how-to-create-new-language)
|
||||
- [Running Environment On Your Localhost](#running-environment-on-your-localhost)
|
||||
- [Express Installation](#express-installation)
|
||||
- [Express Installation with Demo Data](#express-installation-with-demo-data)
|
||||
- [Generate Demo Data for Metered Subscription](#generate-demo-data-for-metered-subscription)
|
||||
- [Generate Demo Data for Fixed Subscription](#generate-demo-data-for-fixed-subscription)
|
||||
- [Sanctum Stateful Domains](#sanctum-stateful-domains)
|
||||
- [Running your Local Server](#running-your-local-server)
|
||||
- [Building Your App for Production](#building-your-app-for-production)
|
||||
- [Others](#others)
|
||||
- [Changelog](#changelog)
|
||||
- [GitHub Repository](#github-repository)
|
||||
- [Support](#support)
|
||||
- [Security Vulnerabilities](#security-vulnerabilities)
|
||||
|
||||
- [Support](#support)
|
||||
- [Security Vulnerabilities](#security-vulnerabilities)
|
||||
|
||||
# Installation
|
||||
## Server Requirements
|
||||
|
||||
**For running app make sure you have:**
|
||||
|
||||
**For running app make sure you have installed:**
|
||||
|
||||
- PHP >= 7.2.5 version
|
||||
- PHP >= 8.0.2 version (8.1+ recommended)
|
||||
- MySQL 5.6+
|
||||
- Nginx or Apache
|
||||
- Nginx or Apache (Nginx recommended)
|
||||
|
||||
**These PHP Extensions are require:**
|
||||
|
||||
|
||||
**These PHP Extensions are required:**
|
||||
|
||||
- Intl
|
||||
- GD
|
||||
- BCMath
|
||||
- PDO
|
||||
- SQLite
|
||||
- SQLite3
|
||||
- Ctype
|
||||
- Fileinfo
|
||||
- JSON
|
||||
@@ -69,60 +58,68 @@ But, it can't be done without you, development is more and more complicated and
|
||||
|
||||
## Installation
|
||||
|
||||
#### 1. Upload files on your server
|
||||
Copy project files to web root folder of your domain. It's mostly located in `html`, `www` or `public_html` folder name.
|
||||
- [How to install VPS with Debian 10](https://medium.com/vuefilemanager/how-to-set-up-vuefilemanager-laravel-application-on-vps-with-debian-10-64676a3ff4d7)
|
||||
- [How to Set Up AWS S3](https://medium.com/vuefilemanager/how-to-set-up-vuefilemanager-with-aws-s3-as-an-external-storage-a2c525aec698)
|
||||
- [How to Set Up Digital Ocean Spaces](https://medium.com/vuefilemanager/how-to-set-up-vuefilemanager-with-digital-ocean-spaces-as-a-external-storage-6cccf590c23d)
|
||||
|
||||
#### 2. Configure your web root folder
|
||||
Configure your web server's document root to point to the public directory of the files you previously uploaded. For example, if you've uploaded the files in `html` folder, your domain root directory should be changed to `html/project_files/public` folder or anything else where domain root is in project `/public` directory.
|
||||
### 1. Upload files on your server
|
||||
Upload project files to the web root folder of your domain. It's mostly located in `html`, `www` or `public_html` folder name.
|
||||
|
||||
Please don't try go to `yourdomain.com/public` URL address, you will have issue to verify your purchase code, this is not correct domain root setup, you must do this in your webhosting settings panel.
|
||||
### 2. Configure your Document Root
|
||||
Configure your domain document root to the point of the files you previously uploaded directly into `/public` folder. So, if you uploaded files into `/public_html` folder, your document root must be set as `/public_html/public`. It should [look like this](https://i.ibb.co/SfLdmCQ/Screenshot-2022-04-06-at-08-53-29.png)
|
||||
|
||||

|
||||
Don't forget to enable Force HTTPS Redirect.
|
||||
|
||||
#### 3. Check your .env file
|
||||
Make sure `.env` file was uploaded. This type of file can be hidden in default.
|
||||
### 3. Set write permissions
|
||||
Set `755` permission (CHMOD) to these files and folders directory within all children subdirectories:
|
||||
|
||||
#### 3.1 When you install from GitHub
|
||||
When you download repository from GitHub, you have to rename your `.env.example` file to `.env`. Then run command below in your terminal to install vendors. Composer is required.
|
||||
```
|
||||
composer install
|
||||
```
|
||||
|
||||
#### 4. Set write permissions
|
||||
Set `755` permission (CHMOD) to these file and folders directory within all children subdirectories:
|
||||
|
||||
- /bootstrap/cache
|
||||
- /bootstrap
|
||||
- /storage
|
||||
- /.env
|
||||
|
||||
#### 5. Open your application in your web browser
|
||||
Then open your application in web browser. If everything works fine, you will be redirect to setup wizard installation process.
|
||||
### 4. Open your application in your web browser
|
||||
Then open your application in web browser. If everything works fine, you will be redirected to the setup wizard installation process.
|
||||
|
||||
At first step you have to verify your purchase code. **Subscription service with stripe payments is available only for Extended License.** If you can't verify your purchase code, check, if you did previously steps correctly.
|
||||
### 5. Server Check
|
||||
On the first page you will see server check. Make sure all items are green. If not, then correct your server setup by recommended values and refresh your setup wizard page.
|
||||
|
||||
#### 6. Follow setup wizard steps
|
||||
### 6. Follow setup wizard steps
|
||||
|
||||
That was the hardest part of installation proces. Please follow instructions in every step of Setup Wizard to successfully install VueFileManager.
|
||||
That was the hardest part of installation process. Please follow instructions in every step of Setup Wizard to successfully install VueFileManager.
|
||||
|
||||
## PHP Configuration
|
||||
There are several PHP settings good to know to setup before you try upload any file. Please set these values in your php.ini, we provide minimal setup for you. When you set `-1` then you set infinity limits.
|
||||
### 7. Set up Cron
|
||||
|
||||
#### If you are running VueFileManager on shared web hosting (CPanel, Plesk etc.)
|
||||
1. Create new cron job
|
||||
2. Set execution cycle every minute
|
||||
3. Search the absolute directory path where you uploaded VueFileManager files (like `/www/project_files`). The path must start with `/`.
|
||||
4. Copy the command below, paste it to the command text area and replace in command string `replace_by_your_path` exactly with your path you found in step 3.
|
||||
5. It should [look like this](https://i.ibb.co/SmR585j/Screenshot-2022-03-31-at-09-30-36.png) with your pasted project path.
|
||||
```
|
||||
memory_limit = 512M
|
||||
upload_max_filesize = 128M
|
||||
post_max_size = 128M
|
||||
max_file_uploads = 50
|
||||
max_execution_time = 3600
|
||||
php replace_by_your_path/artisan schedule:run >> /dev/null 2>&1
|
||||
```
|
||||
6. If you have multiple php versions installed on your server, you should specify php path to the latest php version (8+). So, you should edit `php` in command above and replace it by path. For Example:
|
||||
```
|
||||
/usr/bin/php8.1/php replace_by_your_path/artisan schedule:run >> /dev/null 2>&1
|
||||
```
|
||||
|
||||
## Chunk & Multipart Upload
|
||||
VueFileManager in default supporting chunk upload. Default chunk upload size is `128MB`. If you wish change this default value, go to `/config/vuefilemanager.php` and change `chunk_size` attribute.
|
||||
#### If you are running VueFileManager on linux server
|
||||
1. Search the absolute directory path where you uploaded VueFileManager files (like `/www/project_files`). The path must start with `/`.
|
||||
2. Copy the command below, paste it to your cron list and replace in command string `/www/project_files` exactly with your path you found in step 1.
|
||||
```
|
||||
* * * * * cd /www/project_files && php artisan schedule:run >> /dev/null 2>&1
|
||||
```
|
||||
|
||||
When you use external storage, and upload large files, to prevent failing upload process make sure you have enough space in your application space and set higher `max_execution_time` in your php.ini to move your files to external storage.
|
||||
### 8. CORS Configuration (When you Set External S3 Storage)
|
||||
In your s3 bucket settings you should have option to set up your CORS (Cross-Origin Resource Sharing). It's basically adding your app url to the list of allowed CORS. This step is required for reading pdf documents from s3 in your VueFileManager app without loading issues.
|
||||
|
||||
# Updating Application
|
||||
1. Replace all files where the app is located except `/storage` folder and `.env` file.
|
||||
2. Clear the application cache (Admin / Settings / Application).
|
||||
3. In 5 minutes the app update stuff automatically on the background if needed.
|
||||
|
||||
## Nginx Configuration
|
||||
If you running VueFileManager undex Nginx, don't forget set this value in your `nginx.conf` file:
|
||||
If you running VueFileManager under Nginx, don't forget set this value in your `nginx.conf` file:
|
||||
```
|
||||
http {
|
||||
client_max_body_size 1024M;
|
||||
@@ -182,92 +179,208 @@ Make sure you have enabled mod_rewrite. There is an example config for running V
|
||||
</VirtualHost>
|
||||
```
|
||||
|
||||
## Installation Failed
|
||||
## Migrating to Another Domain
|
||||
If you move your VueFileManager application into another domain or subdomain, you have to manually change values in your `.env` file.
|
||||
1. Open your `/.env` file.
|
||||
2. Find `APP_URL` variable and write your new domain location. Don't forget start with defining `https://` protocol.
|
||||
3. Find `SANCTUM_STATEFUL_DOMAINS` variable and write your new domain location without http protocol.
|
||||
4. Remove your cached config file which is located `/bootstrap/cache/config.php`.
|
||||
|
||||
What to do when installation fail and you can't continue, at first, try to fix issue why installation fail. Probably missing PHP extension or permissions wasn't set correctly.
|
||||
## Social Authentication
|
||||
If you'd like to allow your users to authenticate via their social accounts, the setup is pretty convenient. Just don't forget to set up redirect url and required permissions.
|
||||
|
||||
At worst scenarios, to reset Setup Wizard, delete all tables in your previously created database, delete content of `/storage/framework/cache`. Then replace content in your `.env` file from `.env.example` file.
|
||||
#### Required permissions:
|
||||
- Name and profile picture
|
||||
- Email
|
||||
|
||||
After these steps, installation will be reseted.
|
||||
# Subscription Configuration
|
||||
|
||||
## Update Guide
|
||||
## Configuring Production/Testing Environment
|
||||
To set up your subscription, please follow these steps below.
|
||||
1. If you didn't set up your subscription type in Setup Wizard, go to the `Admin / Settings / Application` and find subscription widget. Next set value as `Fixed`.
|
||||
2. Go to the `Admin / Billings` and fill the inputs with your billing information.
|
||||
3. Go to the `Admin / Payments` and turn on the switch `Allow Subscription Payments`.
|
||||
4. Set up credentials for all payment gateway you want. If you set production mode, make sure you fill your credentials with production keys, and vice versa. If needed, don't forget to turn on `live mode` for PayPal.
|
||||
5. Set up your webhooks, you can find your webhook url in payment gateway widget.
|
||||
6. Go to the `Admin / Plans` and create your first plan. Make sure all payment gateways support the currency you want, especially for Paystack, it supports only `GHS, NGN, USD and ZAR`.
|
||||
|
||||
### Instructions
|
||||
`Don't forget create backup of your database and storage before make any changes in your production application.`
|
||||
## Upgrading From Testing Environment to the Production Mode
|
||||
1. Go to the `Admin / Payments` and set up credentials for all payment gateway you want with production keys type. Don't forget to turn on `live mode` for PayPal.
|
||||
2. Go to the `Admin / Plans` and delete all your previously created plans. They will be archived.
|
||||
3. Create new production plans you want offer.
|
||||
|
||||
`If you serve your files in local storage driver pay attention and don't delete your /storage folder`
|
||||
# Broadcasting
|
||||
### About Broadcasting
|
||||
Broadcasting is responsible for real time app experience. If broadcasting is set, you will be able to get just in time updates in your app.
|
||||
|
||||
Follow this steps:
|
||||
For example, remote upload works on the background, while the files are downloading and showing in your view immediately after they are ready without refreshing the app. Or, you will get immediately notifications about new events like team invitations, file requests and many more.
|
||||
|
||||
- Make a backup of the .env config file located on your server.
|
||||
- Upload and replace all the files on your server with what's inside the app folder.
|
||||
- Restore your `.env` config file on your server.
|
||||
More real time features will be implemented in incoming updates.
|
||||
|
||||
## Update from 1.7.x to 1.7.7
|
||||
If you are upgrading app to 1.7.7 from 1.7.x, make sure you have copied new /vendor folder or if you are using terminal or git, run `composer update` command to update your vendors.
|
||||
VueFileManager support 2 types of connections:
|
||||
1. [Pusher](https://pusher.com/) - Suitable for all users and all hosting platforms
|
||||
2. VueFileManager Broadcast Server - Free of charge, suitable for experienced users, limited for VPS servers
|
||||
|
||||
## Update from 1.6.x to 1.7
|
||||
## Install Broadcast Server
|
||||
We strongly recommend only for experienced users to set up and running VueFileManager broadcast server. For others, we recommend to use Pusher service to easy set up and host broadcasting service.
|
||||
|
||||
For those, who purchase extended licence, place these lines at the end of your `/.env` file:
|
||||
### Server Requirements
|
||||
**For running app make sure you have:**
|
||||
|
||||
- VPS server with SSH access
|
||||
- PHP >= 8.0.2 version (8.1+ recommended)
|
||||
- Nginx
|
||||
- Supervisor
|
||||
- Certbot
|
||||
|
||||
### Installation
|
||||
We assume you have installed and running properly your VPS server.
|
||||
### Websocket Server Set Up
|
||||
Upload VueFileManager into your server, for example path directory `/var/www/sockets` would be great. Next connect to your server with ssh and change your terminal directory into VueFileManager:
|
||||
```
|
||||
CASHIER_LOGGER=stack
|
||||
CASHIER_CURRENCY=
|
||||
STRIPE_KEY=
|
||||
STRIPE_SECRET=
|
||||
STRIPE_WEBHOOK_SECRET=
|
||||
CASHIER_PAYMENT_NOTIFICATION=App\Notifications\ConfirmPayment
|
||||
cd /var/www/sockets
|
||||
```
|
||||
|
||||
Then go to https://your-domain.com/upgrade and follow the setup wizard instructions.
|
||||
|
||||
# Payments
|
||||
VueFileManager is packed with **Stripe** payment options. To configure Stripe, you will be asked in Setup Wizard to set up. Or, if you skip this installation process, you will find stripe set up in you admin `Dashboard / Settings / Payments`.
|
||||
|
||||
## Get your active plans
|
||||
Would you like to get your subscription plans for your custom front-end page? Create GET request and get all your active plans:
|
||||
Run installation command for websocket server. You will be prompted to type host of which you want to allow incoming requests.
|
||||
```
|
||||
GET /api/public/pricing
|
||||
php artisan websockets:install
|
||||
```
|
||||
### Domain & Nginx Set Up
|
||||
Create subdomain for your socket host, for example `socket.vuefilemanager.com` and direct this subdomain to your vps where socket server will be running.
|
||||
|
||||
## Manage Failed Payments
|
||||
VueFileManager manage failed payments with additional email notification. But, there is more you can do for better User Experience. There is some additionals option in Stripe, look on [prevent failed payments](https://dashboard.stripe.com/settings/billing/automatic).
|
||||
Then, create nginx config for your subdomain:
|
||||
```
|
||||
nano /etc/nginx/sites-available/socket.conf
|
||||
```
|
||||
And paste the template below, just replace subdomain with yours:
|
||||
```
|
||||
server {
|
||||
listen 80;
|
||||
server_name socket.vuefilemanager.com;
|
||||
|
||||
## Tax Rates
|
||||
You are able to manage tax rates. When adding a new tax rate, if no Region is specified, the tax rate will apply to everyone. Add a [ISO 3166-1 alpha-2 country code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) to the Region field if you wish to apply taxes per country.
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:6001;
|
||||
proxy_read_timeout 60;
|
||||
proxy_connect_timeout 60;
|
||||
proxy_redirect off;
|
||||
|
||||
Just log in to your stripe dashboard, and you will find taxes under `Dashboard / Products / Tax Rates`.
|
||||
# Allow the use of websockets
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
proxy_set_header Host $host;
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
}
|
||||
}
|
||||
```
|
||||
Enable your created config by this command:
|
||||
```
|
||||
ln -s /etc/nginx/sites-available/socket.conf /etc/nginx/sites-enabled/
|
||||
```
|
||||
Restart your nginx:
|
||||
```
|
||||
systemctl restart nginx
|
||||
```
|
||||
In the last step, install ssl certificate for your previously created subdomain with certbot:
|
||||
```
|
||||
certbot --nginx
|
||||
```
|
||||
### Supervisor Configuration
|
||||
We need supervisor to manage running your websocket server on the background.
|
||||
In `/etc/supervisor/conf.d` (Debian/Ubuntu) or `/etc/supervisord.d/` (Red Hat/CentOS) create a file `websockets.conf`.
|
||||
|
||||
Just edit php path, project path and user when they are different for your vps:
|
||||
```
|
||||
[program:websockets]
|
||||
command=/usr/bin/php /var/www/socket/artisan websockets:serve
|
||||
numprocs=1
|
||||
autostart=true
|
||||
autorestart=true
|
||||
user=www-data
|
||||
```
|
||||
Run command below to start your websocket server:
|
||||
```
|
||||
supervisorctl start websockets
|
||||
```
|
||||
Run command below to stop your websocket server:
|
||||
```
|
||||
supervisorctl stop websockets
|
||||
```
|
||||
When you update code or server for some reason, you must also update running supervisor:
|
||||
```
|
||||
supervisorctl reload
|
||||
```
|
||||
### VueFileManager Set Up
|
||||
Log in to your VueFileManager admin account and go to `Admin / Settings / Environment`.
|
||||
|
||||
Find Broadcasting form and select `VueFileManager` as broadcasting driver. Set your hostname and save the form.
|
||||
|
||||
That's all, you are running your own Broadcast server.
|
||||
|
||||
# Developers
|
||||
## Running development environment on your localhost
|
||||
## Running Environment On Your Localhost
|
||||
|
||||
When you download repository from GitHub, you have to rename your `.env.example` file to `.env`. Then run command below in your terminal to install vendors. Composer is required.
|
||||
**For running development environment make sure you have:**
|
||||
|
||||
- Node >= 14
|
||||
- NPM >= 6
|
||||
|
||||
### Express Installation
|
||||
If you would like to have express installation without Setup Wizard process, please update your database credentials in .env file
|
||||
```
|
||||
composer install
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=laravel
|
||||
DB_USERNAME=root
|
||||
DB_PASSWORD=
|
||||
```
|
||||
Next, run this command below. Admin account will be created with credentials `howdy@hi5ve.digital` and password `vuefilemanager`.
|
||||
```
|
||||
php artisan setup:prod
|
||||
```
|
||||
|
||||
Set your `APP_ENV` to local mode, in default, it's in production mode.
|
||||
### Express Installation with Demo Data
|
||||
If you would like to generate demo content, run this command below. Admin account will be created with credentials `howdy@hi5ve.digital` and password `vuefilemanager`.
|
||||
```
|
||||
APP_ENV=local
|
||||
php artisan setup:dev
|
||||
```
|
||||
|
||||
Also, to debug application, set `APP_DEBUG` on true:
|
||||
### Generate Demo Data for Metered Subscription
|
||||
If you would like to generate demo content for the subscription with the metered billing, run this command below.
|
||||
```
|
||||
APP_DEBUG=true
|
||||
php artisan subscription:demo metered
|
||||
```
|
||||
|
||||
To start server on your localhost, run command below. Then go to your generated localhost URL by terminal, and follow Setup Wizard steps to configure VueFileManager.
|
||||
### Generate Demo Data for Fixed Subscription
|
||||
If you would like to generate demo content for the subscription with the fixed billing, please fill the credentials in your `.env` file for the payment systems you'd like to use:
|
||||
```
|
||||
STRIPE_SECRET_KEY=
|
||||
STRIPE_PUBLIC_KEY=
|
||||
STRIPE_WEBHOOK_SECRET=
|
||||
|
||||
PAYSTACK_SECRET=
|
||||
PAYSTACK_PUBLIC_KEY=
|
||||
|
||||
PAYPAL_CLIENT_ID=
|
||||
PAYPAL_CLIENT_SECRET=
|
||||
PAYPAL_WEBHOOK_ID=
|
||||
PAYPAL_IS_LIVE=false
|
||||
```
|
||||
and then run this command to generate demo content for fixed subscription:
|
||||
```
|
||||
php artisan subscription:demo fixed
|
||||
```
|
||||
|
||||
### Sanctum Stateful Domains
|
||||
After installation, please make sure your current host/domain where you are running app is included in your `.env` file in `SANCTUM_STATEFUL_DOMAINS` variable.
|
||||
|
||||
### Running your Local Server
|
||||
To start server on your localhost, run command below.
|
||||
```
|
||||
php artisan serve
|
||||
```
|
||||
|
||||
After successfully installation via Setup Wizard, stop your artisan server, clear config cache and run your artisan server again:
|
||||
```
|
||||
php artisan config:clear
|
||||
php artisan serve
|
||||
```
|
||||
*After any change in your .env you have to restart your artisan server to reload your config cache.*
|
||||
|
||||
To develop your Vue front-end, you have to install npm modules by this command:
|
||||
For developing Vue front-end, you have to install npm modules by this command:
|
||||
```
|
||||
npm install
|
||||
```
|
||||
@@ -277,87 +390,25 @@ To compiles and hot-reloads for front-end development. Then run this command:
|
||||
npm run hot
|
||||
```
|
||||
|
||||
### Building Your App for Production
|
||||
To compiles for production build, run this command
|
||||
```
|
||||
npm run prod
|
||||
```
|
||||
|
||||
## Supported Storages
|
||||
VueFileManager support these storages for your files:
|
||||
|
||||
- [Amazon Web Services S3](https://aws.amazon.com/s3/)
|
||||
- [Digital Ocean Spaces](https://www.digitalocean.com/products/spaces/)
|
||||
- [Object Cloud Storage by Wasabi](https://wasabi.com/)
|
||||
- [Backblaze B2 Cloud Storage](https://www.backblaze.com/b2/cloud-storage.html)
|
||||
- Your local disk
|
||||
|
||||
In case of installation process, you will be able to set storage driver and credentials. After this, you can change your credentials later in `/.env` file.
|
||||
|
||||
To set or change your storage driver, you have to edit `FILESYSTEM_DRIVER` in your `/.env` file. Supported drivers are `s3`, `spaces`, `wasabi`,`backblaze` or `local`:
|
||||
```
|
||||
FILESYSTEM_DRIVER=local
|
||||
```
|
||||
Then you can find corresponding credentials options for your storage driver like key, secret, region in `/.env` file.
|
||||
|
||||
|
||||
## How to Create New Language
|
||||
VueFileManager front-end support i18n standard for localization. This mean, you can translate app to any language
|
||||
|
||||
### How to create translation for Vue Front-End
|
||||
Go to `/resources/js/i18n/lang` And make copy of `en.json` and rename it to your local name (eg: Slovak language has 'sk' shortcut, it means `sk.json`). If you have created your copy, then feel free to translate this file.
|
||||
|
||||
Open `/resources/js/i18n/index.js` import your new language and assign it to languages object:
|
||||
|
||||
```
|
||||
import Vue from 'vue';
|
||||
import VueI18n from 'vue-i18n';
|
||||
|
||||
import en from './lang/en.json'
|
||||
import sk from './lang/sk.json'
|
||||
|
||||
Vue.use(VueI18n);
|
||||
|
||||
const i18n = new VueI18n({
|
||||
locale: config.locale,
|
||||
messages: Object.assign({
|
||||
en,
|
||||
sk
|
||||
}),
|
||||
});
|
||||
|
||||
export default i18n;
|
||||
```
|
||||
After this, you have to compile language to your application code via this command in your terminal:
|
||||
```
|
||||
npm run prod
|
||||
```
|
||||
|
||||
### How to Create Translation for Laravel Back-End
|
||||
Go to `/resources/lang/` And make copy of `en` folder and rename it to your local name (eg: Slovak language has 'sk' shortcut, it means `sk`). If you have created your copy, then feel free to translate this file.
|
||||
|
||||
### Set locale
|
||||
To set your locale in app, go to `/config/app.php` and set your locale string in `locale` option:
|
||||
|
||||
```
|
||||
'locale' => 'YOUR_LOCALE',
|
||||
```
|
||||
|
||||
**Small hint:** We use for translating localizations this awesome software, [check it](https://www.codeandweb.com/babeledit).
|
||||
|
||||
# Others
|
||||
## Changelog
|
||||
|
||||
Refer to the [Changelog](https://vuefilemanager.com/changelog) for a full history of the project.
|
||||
|
||||
## GitHub Repository
|
||||
[Join our GitHub repository](https://vuefilemanager.com/github-access) to submit your issues or suggestions, track VueFileManager progress and get new updates as fast as possible.
|
||||
|
||||
## Support
|
||||
|
||||
The following support channels are available at your fingertips:
|
||||
|
||||
- [CodeCanyon support message](https://codecanyon.net/item/vue-file-manager-with-laravel-backend/25815986/support)
|
||||
- [GitHub repository](https://vuefilemanager.com/github-access)
|
||||
|
||||
## Supporting VueFileManager
|
||||
We are trying to make the best for VueFileManager. There are a lot of things to do, and a lot of features we can make.
|
||||
But, it can't be done without you, development is more and more complicated and we have to hire new colleagues to help us. There is couple way you can support us, and then, we support you with all great new features we can make. Thank you for participating on this awesome application!
|
||||
|
||||
- [Buy me a Coffee](https://www.buymeacoffee.com/pepe)
|
||||
- [Become a Patreon](https://www.patreon.com/vuefilemanager)
|
||||
- [One-time donation via PayPal](https://www.paypal.me/peterpapp)
|
||||
|
||||
## Security Vulnerabilities
|
||||
|
||||
|
||||
2432
_ide_helper.php
2432
_ide_helper.php
File diff suppressed because it is too large
Load Diff
@@ -1,66 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class Deploy extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'deploy:production';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Automatic deployment for production';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
// Start deployment
|
||||
$this->info('Running auto deployment');
|
||||
$this->call('down');
|
||||
|
||||
// Exec commands
|
||||
exec('git pull origin ' . config('app.deploy_branch'));
|
||||
//exec('composer update --no-interaction --prefer-dist');
|
||||
$this->migrateDatabase();
|
||||
|
||||
// Stop deployment
|
||||
$this->call('up');
|
||||
$this->info('Everything is done, congratulations! 🥳🥳🥳');
|
||||
|
||||
Log::info('Application was updated!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrate database
|
||||
*/
|
||||
public function migrateDatabase()
|
||||
{
|
||||
$this->call('migrate', [
|
||||
'--force' => true,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console;
|
||||
|
||||
use App\Console\Commands\Deploy;
|
||||
use App\Console\Commands\SetupDevEnvironment;
|
||||
use App\Console\Commands\SetupProductionEnvironment;
|
||||
use App\Console\Commands\UpgradeApp;
|
||||
use Illuminate\Console\Scheduling\Schedule;
|
||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||
|
||||
class Kernel extends ConsoleKernel
|
||||
{
|
||||
/**
|
||||
* The Artisan commands provided by your application.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $commands = [
|
||||
Deploy::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* Define the application's command schedule.
|
||||
*
|
||||
* @param \Illuminate\Console\Scheduling\Schedule $schedule
|
||||
* @return void
|
||||
*/
|
||||
protected function schedule(Schedule $schedule)
|
||||
{
|
||||
// $schedule->command('inspire')
|
||||
// ->hourly();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the commands for the application.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function commands()
|
||||
{
|
||||
$this->load(__DIR__.'/Commands');
|
||||
|
||||
require base_path('routes/console.php');
|
||||
}
|
||||
}
|
||||
@@ -1,220 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use ByteUnits\Metric;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Laravel\Scout\Searchable;
|
||||
use TeamTNT\TNTSearch\Indexer\TNTIndexer;
|
||||
use \Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
/**
|
||||
* App\FileManagerFile
|
||||
*
|
||||
* @property int $id
|
||||
* @property int|null $user_id
|
||||
* @property int $unique_id
|
||||
* @property int $folder_id
|
||||
* @property string $thumbnail
|
||||
* @property string|null $name
|
||||
* @property string|null $basename
|
||||
* @property string|null $mimetype
|
||||
* @property string $filesize
|
||||
* @property string|null $type
|
||||
* @property string $user_scope
|
||||
* @property string $deleted_at
|
||||
* @property string $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property-read \App\FileManagerFolder|null $folder
|
||||
* @property-read string $file_url
|
||||
* @property-read \App\FileManagerFolder $parent
|
||||
* @property-read \App\Share|null $shared
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile newQuery()
|
||||
* @method static \Illuminate\Database\Query\Builder|\App\FileManagerFile onlyTrashed()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile query()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereBasename($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereCreatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereDeletedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereFilesize($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereFolderId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereMimetype($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereName($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereThumbnail($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereType($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereUniqueId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereUpdatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereUserId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereUserScope($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\App\FileManagerFile withTrashed()
|
||||
* @method static \Illuminate\Database\Query\Builder|\App\FileManagerFile withoutTrashed()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class FileManagerFile extends Model
|
||||
{
|
||||
use Searchable, SoftDeletes;
|
||||
|
||||
public $public_access = null;
|
||||
|
||||
protected $guarded = [
|
||||
'id'
|
||||
];
|
||||
|
||||
protected $appends = [
|
||||
'file_url'
|
||||
];
|
||||
|
||||
/**
|
||||
* Set routes with public access
|
||||
*
|
||||
* @param $token
|
||||
*/
|
||||
public function setPublicUrl($token)
|
||||
{
|
||||
$this->public_access = $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format created at date
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCreatedAtAttribute()
|
||||
{
|
||||
return format_date($this->attributes['created_at'], __('vuefilemanager.time'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Form\a\t created at date reformat
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDeletedAtAttribute()
|
||||
{
|
||||
if (!$this->attributes['deleted_at']) return null;
|
||||
|
||||
return format_date($this->attributes['deleted_at'], __('vuefilemanager.time'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Format fileSize
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFilesizeAttribute()
|
||||
{
|
||||
return Metric::bytes($this->attributes['filesize'])->format();
|
||||
}
|
||||
|
||||
/**
|
||||
* Format thumbnail url
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getThumbnailAttribute()
|
||||
{
|
||||
// Get thumbnail from external storage
|
||||
if ($this->attributes['thumbnail'] && is_storage_driver(['s3', 'spaces', 'wasabi', 'backblaze'])) {
|
||||
|
||||
return Storage::temporaryUrl('file-manager/' . $this->attributes['thumbnail'], now()->addHour());
|
||||
}
|
||||
|
||||
// Get thumbnail from local storage
|
||||
if ($this->attributes['thumbnail']) {
|
||||
|
||||
// Thumbnail route
|
||||
$route = route('thumbnail', ['name' => $this->attributes['thumbnail']]);
|
||||
|
||||
if ($this->public_access) {
|
||||
return $route . '/public/' . $this->public_access;
|
||||
}
|
||||
|
||||
return $route;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format file url
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFileUrlAttribute()
|
||||
{
|
||||
// Get file from external storage
|
||||
if (is_storage_driver(['s3', 'spaces', 'wasabi', 'backblaze'])) {
|
||||
|
||||
$file_pretty_name = get_pretty_name($this->attributes['basename'], $this->attributes['name'], $this->attributes['mimetype']);
|
||||
|
||||
$header = [
|
||||
"ResponseAcceptRanges" => "bytes",
|
||||
"ResponseContentType" => $this->attributes['mimetype'],
|
||||
"ResponseContentLength" => $this->attributes['filesize'],
|
||||
"ResponseContentRange" => "bytes 0-600/" . $this->attributes['filesize'],
|
||||
'ResponseContentDisposition' => 'attachment; filename=' . $file_pretty_name,
|
||||
];
|
||||
|
||||
return Storage::temporaryUrl('file-manager/' . $this->attributes['basename'], now()->addDay(), $header);
|
||||
}
|
||||
|
||||
// Get thumbnail from local storage
|
||||
$route = route('file', ['name' => $this->attributes['basename']]);
|
||||
|
||||
if ($this->public_access) {
|
||||
return $route . '/public/' . $this->public_access;
|
||||
}
|
||||
|
||||
return $route;
|
||||
}
|
||||
|
||||
/**
|
||||
* Index file
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toSearchableArray()
|
||||
{
|
||||
$array = $this->toArray();
|
||||
$name = Str::slug($array['name'], ' ');
|
||||
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'name' => $name,
|
||||
'nameNgrams' => utf8_encode((new TNTIndexer)->buildTrigrams(implode(', ', [$name]))),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get parent
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function parent()
|
||||
{
|
||||
return $this->belongsTo('App\FileManagerFolder', 'folder_id', 'unique_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get folder
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasOne
|
||||
*/
|
||||
public function folder()
|
||||
{
|
||||
return $this->hasOne('App\FileManagerFolder', 'unique_id', 'folder_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get sharing attributes
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasOne
|
||||
*/
|
||||
public function shared()
|
||||
{
|
||||
return $this->hasOne('App\Share', 'item_id', 'unique_id');
|
||||
}
|
||||
}
|
||||
@@ -1,263 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
use Laravel\Scout\Searchable;
|
||||
use RecursiveArrayIterator;
|
||||
use RecursiveIteratorIterator;
|
||||
use TeamTNT\TNTSearch\Indexer\TNTIndexer;
|
||||
use \Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
/**
|
||||
* App\FileManagerFolder
|
||||
*
|
||||
* @property int $id
|
||||
* @property int|null $user_id
|
||||
* @property int $unique_id
|
||||
* @property int $parent_id
|
||||
* @property string|null $name
|
||||
* @property string|null $type
|
||||
* @property string $user_scope
|
||||
* @property string $deleted_at
|
||||
* @property string $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\FileManagerFolder[] $children
|
||||
* @property-read int|null $children_count
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\FileManagerFile[] $files
|
||||
* @property-read int|null $files_count
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\FileManagerFolder[] $folders
|
||||
* @property-read int|null $folders_count
|
||||
* @property-read int $items
|
||||
* @property-read int $trashed_items
|
||||
* @property-read \App\FileManagerFolder $parent
|
||||
* @property-read \App\Share|null $shared
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\FileManagerFolder[] $trashed_children
|
||||
* @property-read int|null $trashed_children_count
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\FileManagerFile[] $trashed_files
|
||||
* @property-read int|null $trashed_files_count
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\FileManagerFolder[] $trashed_folders
|
||||
* @property-read int|null $trashed_folders_count
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder newQuery()
|
||||
* @method static \Illuminate\Database\Query\Builder|\App\FileManagerFolder onlyTrashed()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder query()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder whereCreatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder whereDeletedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder whereId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder whereName($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder whereParentId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder whereType($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder whereUniqueId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder whereUpdatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder whereUserId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder whereUserScope($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\App\FileManagerFolder withTrashed()
|
||||
* @method static \Illuminate\Database\Query\Builder|\App\FileManagerFolder withoutTrashed()
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class FileManagerFolder extends Model
|
||||
{
|
||||
use Searchable, SoftDeletes;
|
||||
|
||||
protected $guarded = [
|
||||
'id'
|
||||
];
|
||||
|
||||
protected $appends = [
|
||||
'items', 'trashed_items'
|
||||
];
|
||||
|
||||
/**
|
||||
* Index folder
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toSearchableArray()
|
||||
{
|
||||
$array = $this->toArray();
|
||||
$name = Str::slug($array['name'], ' ');
|
||||
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'name' => $name,
|
||||
'nameNgrams' => utf8_encode((new TNTIndexer)->buildTrigrams(implode(', ', [$name]))),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts how many folder have items
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getItemsAttribute()
|
||||
{
|
||||
$folders = $this->folders()->count();
|
||||
$files = $this->files()->count();
|
||||
|
||||
return $folders + $files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts how many folder have items
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getTrashedItemsAttribute()
|
||||
{
|
||||
$folders = $this->trashed_folders()->count();
|
||||
$files = $this->trashed_files()->count();
|
||||
|
||||
return $folders + $files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format created at date reformat
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCreatedAtAttribute()
|
||||
{
|
||||
return format_date($this->attributes['created_at'], __('vuefilemanager.time'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Format created at date reformat
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDeletedAtAttribute()
|
||||
{
|
||||
if (! $this->attributes['deleted_at']) return null;
|
||||
|
||||
return format_date($this->attributes['deleted_at'], __('vuefilemanager.time'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get parent
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function parent()
|
||||
{
|
||||
return $this->belongsTo('App\FileManagerFolder', 'parent_id', 'unique_id');
|
||||
}
|
||||
|
||||
public function folderIds()
|
||||
{
|
||||
return $this->children()->with('folderIds')->select(['unique_id', 'parent_id']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all files
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function files()
|
||||
{
|
||||
return $this->hasMany('App\FileManagerFile', 'folder_id', 'unique_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all trashed files
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function trashed_files()
|
||||
{
|
||||
|
||||
return $this->hasMany('App\FileManagerFile', 'folder_id', 'unique_id')->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all folders
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function folders()
|
||||
{
|
||||
return $this->children()->with('folders');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all trashed folders
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function trashed_folders()
|
||||
{
|
||||
return $this->children()->with('trashed_folders')->withTrashed()->select(['parent_id', 'unique_id', 'name']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get childrens
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function children()
|
||||
{
|
||||
return $this->hasMany('App\FileManagerFolder', 'parent_id', 'unique_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get trashed childrens
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function trashed_children()
|
||||
{
|
||||
return $this->hasMany('App\FileManagerFolder', 'parent_id', 'unique_id')->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get sharing attributes
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasOne
|
||||
*/
|
||||
public function shared()
|
||||
{
|
||||
return $this->hasOne('App\Share', 'item_id', 'unique_id');
|
||||
}
|
||||
|
||||
// Delete all folder childrens
|
||||
public static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
static::deleting(function ($item) {
|
||||
|
||||
if ( $item->isForceDeleting() ) {
|
||||
|
||||
$item->trashed_children()->each(function($folder) {
|
||||
$folder->forceDelete();
|
||||
});
|
||||
|
||||
} else {
|
||||
|
||||
$item->children()->each(function($folder) {
|
||||
$folder->delete();
|
||||
});
|
||||
|
||||
$item->files()->each(function($file) {
|
||||
$file->delete();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
static::restoring(function ($item) {
|
||||
|
||||
// Restore children folders
|
||||
$item->trashed_children()->each(function($folder) {
|
||||
$folder->restore();
|
||||
});
|
||||
|
||||
// Restore children files
|
||||
$item->trashed_files()->each(function($files) {
|
||||
$files->restore();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\FileManagerFile;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\UsersCollection;
|
||||
use App\Services\StripeService;
|
||||
use App\Setting;
|
||||
use App\User;
|
||||
use ByteUnits\Metric;
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Cashier\Subscription;
|
||||
|
||||
class DashboardController extends Controller
|
||||
{
|
||||
/**
|
||||
* DashboardController constructor.
|
||||
*/
|
||||
public function __construct(StripeService $stripe)
|
||||
{
|
||||
$this->stripe = $stripe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get data for dashboard
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
// Get total users
|
||||
$total_users = User::all()->count();
|
||||
|
||||
// Get total used space
|
||||
$total_used_space = FileManagerFile::all()->map(function ($item) {
|
||||
return (int)$item->getRawOriginal('filesize');
|
||||
})->sum();
|
||||
|
||||
// Get total premium users
|
||||
$total_premium_users = Subscription::where('stripe_status', 'active')->get()->count();
|
||||
|
||||
// Get License
|
||||
$license = Setting::where('name', 'license')->first();
|
||||
|
||||
return [
|
||||
'license' => $license ? $license->value : null,
|
||||
'app_version' => config('vuefilemanager.version'),
|
||||
'total_users' => $total_users,
|
||||
'total_used_space' => Metric::bytes($total_used_space)->format(),
|
||||
'total_premium_users' => $total_premium_users,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the newest users
|
||||
*
|
||||
* @return UsersCollection
|
||||
*/
|
||||
public function new_registrations()
|
||||
{
|
||||
return new UsersCollection(
|
||||
User::sortable(['created_at' => 'desc'])->paginate(10)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\InvoiceAdminCollection;
|
||||
use App\Http\Resources\InvoiceResource;
|
||||
use App\Invoice;
|
||||
use App\Services\StripeService;
|
||||
use App\Setting;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class InvoiceController extends Controller
|
||||
{
|
||||
/**
|
||||
* PlanController constructor.
|
||||
*/
|
||||
public function __construct(StripeService $stripe)
|
||||
{
|
||||
$this->stripe = $stripe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all invoices
|
||||
*
|
||||
* @return InvoiceAdminCollection
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return new InvoiceAdminCollection(
|
||||
$this->stripe->getInvoices()['data']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get single invoice by $token
|
||||
*
|
||||
* @param $customer
|
||||
* @param $token
|
||||
* @return InvoiceResource
|
||||
*/
|
||||
public function show($customer, $token)
|
||||
{
|
||||
$settings = json_decode(Setting::all()->pluck('value', 'name')->toJson());
|
||||
|
||||
$invoice = $this->stripe->getUserInvoice($customer, $token);
|
||||
|
||||
return view('vuefilemanager.invoice')
|
||||
->with('settings', $settings)
|
||||
->with('invoice', $invoice);
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\PageCollection;
|
||||
use App\Http\Resources\PageResource;
|
||||
use App\Http\Tools\Demo;
|
||||
use App\Page;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class PagesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get all pages
|
||||
*
|
||||
* @return PageCollection
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return new PageCollection(
|
||||
Page::sortable()->paginate(10)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get page resource
|
||||
*
|
||||
* @param $slug
|
||||
* @return PageResource
|
||||
*/
|
||||
public function show($slug)
|
||||
{
|
||||
return new PageResource(
|
||||
Page::where('slug', $slug)->first()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update page content
|
||||
*
|
||||
* @param Request $request
|
||||
* @param $slug
|
||||
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function update(Request $request, $slug)
|
||||
{
|
||||
// Check if is demo
|
||||
if (env('APP_DEMO')) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Get page
|
||||
$page = Page::where('slug', $slug)->first();
|
||||
|
||||
// Update page
|
||||
$page->update(make_single_input($request));
|
||||
|
||||
return response('Done', 204);
|
||||
}
|
||||
}
|
||||
@@ -1,159 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\PlanCollection;
|
||||
use App\Http\Resources\PlanResource;
|
||||
use App\Http\Resources\UserResource;
|
||||
use App\Http\Resources\UsersCollection;
|
||||
use App\Http\Tools\Demo;
|
||||
use App\Plan;
|
||||
use App\Services\StripeService;
|
||||
use App\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Laravel\Cashier\Subscription;
|
||||
use Rinvex\Subscriptions\Models\PlanFeature;
|
||||
|
||||
class PlanController extends Controller
|
||||
{
|
||||
/**
|
||||
* PlanController constructor.
|
||||
*/
|
||||
public function __construct(StripeService $stripe)
|
||||
{
|
||||
$this->stripe = $stripe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all plans
|
||||
*
|
||||
* @return PlanCollection
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
// Store or Get plans to cache
|
||||
if (Cache::has('plans')) {
|
||||
$plans = Cache::get('plans');
|
||||
} else {
|
||||
$plans = Cache::rememberForever('plans', function () {
|
||||
return $this->stripe->getPlans();
|
||||
});
|
||||
}
|
||||
|
||||
return new PlanCollection($plans);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get plan record
|
||||
*
|
||||
* @param $id
|
||||
* @return PlanResource
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
// Store or Get plan to cache
|
||||
if (Cache::has('plan-' . $id)) {
|
||||
$plan = Cache::get('plan-' . $id);
|
||||
} else {
|
||||
$plan = Cache::rememberForever('plan-' . $id, function () use ($id) {
|
||||
return $this->stripe->getPlan($id);
|
||||
});
|
||||
}
|
||||
|
||||
return new PlanResource($plan);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new plan
|
||||
*
|
||||
* @param Request $request
|
||||
* @return PlanResource
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
// Check if is demo
|
||||
if (env('APP_DEMO')) {
|
||||
|
||||
if (Cache::has('plan-starter-pack')) {
|
||||
$plan = Cache::get('plan-starter-pack');
|
||||
} else {
|
||||
$plan = Cache::rememberForever('plan-starter-pack', function () {
|
||||
return $this->stripe->getPlan('starter-pack');
|
||||
});
|
||||
}
|
||||
|
||||
return new PlanResource($plan);
|
||||
}
|
||||
|
||||
$plan = new PlanResource(
|
||||
$this->stripe->createPlan($request)
|
||||
);
|
||||
|
||||
// Clear cached plans
|
||||
cache_forget_many(['plans', 'pricing']);
|
||||
|
||||
return $plan;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update plan attribute
|
||||
*
|
||||
* @param Request $request
|
||||
* @param $id
|
||||
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
// Check if is demo
|
||||
if (env('APP_DEMO')) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Update plan
|
||||
$this->stripe->updatePlan($request, $id);
|
||||
|
||||
// Clear cached plans
|
||||
cache_forget_many(['plans', 'pricing', 'plan-' . $id]);
|
||||
|
||||
return response('Saved!', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete plan
|
||||
*
|
||||
* @param $id
|
||||
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
// Check if is demo
|
||||
if (env('APP_DEMO')) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Delete plan
|
||||
$this->stripe->deletePlan($id);
|
||||
|
||||
// Clear cached plans
|
||||
cache_forget_many(['plans', 'pricing']);
|
||||
|
||||
return response('Done!', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get subscriptions
|
||||
*
|
||||
* @param $id
|
||||
* @return mixed
|
||||
*/
|
||||
public function subscribers($id)
|
||||
{
|
||||
$subscribers = Subscription::where('stripe_plan', $id)->pluck('user_id');
|
||||
|
||||
return new UsersCollection(
|
||||
User::sortable()->findMany($subscribers)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,274 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\FileManagerFile;
|
||||
use App\FileManagerFolder;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Admin\ChangeRoleRequest;
|
||||
use App\Http\Requests\Admin\ChangeStorageCapacityRequest;
|
||||
use App\Http\Requests\Admin\CreateUserByAdmin;
|
||||
use App\Http\Requests\Admin\DeleteUserRequest;
|
||||
use App\Http\Resources\InvoiceCollection;
|
||||
use App\Http\Resources\UsersCollection;
|
||||
use App\Http\Resources\UserResource;
|
||||
use App\Http\Resources\UserStorageResource;
|
||||
use App\Http\Resources\UserSubscription;
|
||||
use App\Http\Tools\Demo;
|
||||
use App\Services\StripeService;
|
||||
use App\Share;
|
||||
use App\User;
|
||||
use App\UserSettings;
|
||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
use Illuminate\Support\Str;
|
||||
use Storage;
|
||||
|
||||
class UserController extends Controller
|
||||
{
|
||||
public function __construct(StripeService $stripe)
|
||||
{
|
||||
$this->stripe = $stripe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user details
|
||||
*
|
||||
* @param $id
|
||||
* @return UserResource
|
||||
*/
|
||||
public function details($id)
|
||||
{
|
||||
return new UserResource(
|
||||
User::findOrFail($id)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user storage details
|
||||
*
|
||||
* @param $id
|
||||
* @return UserStorageResource
|
||||
*/
|
||||
public function storage($id)
|
||||
{
|
||||
return new UserStorageResource(
|
||||
User::findOrFail($id)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user storage details
|
||||
*
|
||||
* @return InvoiceCollection
|
||||
*/
|
||||
public function invoices($id)
|
||||
{
|
||||
$user = User::find($id);
|
||||
|
||||
return new InvoiceCollection(
|
||||
$this->stripe->getUserInvoices($user)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user subscription details
|
||||
*
|
||||
* @param $id
|
||||
* @return UserSubscription
|
||||
*/
|
||||
public function subscription($id)
|
||||
{
|
||||
$user = User::find($id);
|
||||
|
||||
if (! $user->stripeId() || ! $user->subscription('main')) {
|
||||
return response('User doesn\'t have any subscription.', 404);
|
||||
}
|
||||
|
||||
return new UserSubscription(
|
||||
User::find($id)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all users
|
||||
*
|
||||
* @return UsersCollection
|
||||
*/
|
||||
public function users()
|
||||
{
|
||||
return new UsersCollection(
|
||||
User::sortable()->paginate('20')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change user role
|
||||
*
|
||||
* @param ChangeRoleRequest $request
|
||||
* @param $id
|
||||
* @return UserResource
|
||||
*/
|
||||
public function change_role(ChangeRoleRequest $request, $id)
|
||||
{
|
||||
$user = User::findOrFail($id);
|
||||
|
||||
// Demo preview
|
||||
if (env('APP_DEMO') && $id == 1) {
|
||||
return new UserResource($user);
|
||||
}
|
||||
|
||||
// Update user role
|
||||
$user->role = $request->input('attributes.role');
|
||||
$user->save();
|
||||
|
||||
return new UserResource($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change user storage capacity
|
||||
*
|
||||
* @param ChangeStorageCapacityRequest $request
|
||||
* @param $id
|
||||
* @return UserStorageResource
|
||||
*/
|
||||
public function change_storage_capacity(ChangeStorageCapacityRequest $request, $id)
|
||||
{
|
||||
$user = User::findOrFail($id);
|
||||
|
||||
$user->settings()->update($request->input('attributes'));
|
||||
|
||||
return new UserStorageResource($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send user password reset link
|
||||
*
|
||||
* @param $id
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function send_password_reset_email($id)
|
||||
{
|
||||
$user = User::findOrFail($id);
|
||||
|
||||
// Demo preview
|
||||
if (env('APP_DEMO')) {
|
||||
return response('Done!', 204);
|
||||
}
|
||||
|
||||
// Get password token
|
||||
$token = Password::getRepository()->create($user);
|
||||
|
||||
// Send user email
|
||||
$user->sendPasswordResetNotification($token);
|
||||
|
||||
return response('Done!', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new user by admin
|
||||
*
|
||||
* @param CreateUserByAdmin $request
|
||||
* @return UserResource
|
||||
*/
|
||||
public function create_user(CreateUserByAdmin $request)
|
||||
{
|
||||
// Store avatar
|
||||
if ($request->hasFile('avatar')) {
|
||||
$avatar = store_avatar($request->file('avatar'), 'avatars');
|
||||
}
|
||||
|
||||
// Create user
|
||||
$user = User::forceCreate([
|
||||
'avatar' => $request->hasFile('avatar') ? $avatar : null,
|
||||
'name' => $request->name,
|
||||
'role' => $request->role,
|
||||
'email' => $request->email,
|
||||
'password' => Hash::make($request->password),
|
||||
]);
|
||||
|
||||
// Create settings
|
||||
UserSettings::forceCreate([
|
||||
'user_id' => $user->id,
|
||||
'storage_capacity' => $request->storage_capacity,
|
||||
]);
|
||||
|
||||
return new UserResource($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete user with all user data
|
||||
*
|
||||
* @param DeleteUserRequest $request
|
||||
* @param $id
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function delete_user(DeleteUserRequest $request, $id)
|
||||
{
|
||||
$user = User::findOrFail($id);
|
||||
|
||||
if ($user->subscribed('main')) {
|
||||
abort(202, 'You can\'t delete this account while user have active subscription.');
|
||||
}
|
||||
|
||||
// Demo preview
|
||||
if (env('APP_DEMO')) {
|
||||
return response('Done!', 204);
|
||||
}
|
||||
|
||||
// Check for self deleted account
|
||||
if ($user->id === Auth::id()) {
|
||||
abort(406, 'You can\'t delete your account');
|
||||
}
|
||||
|
||||
// Validate user name
|
||||
if ($user->name !== $request->input('data.name')) abort(403);
|
||||
|
||||
$shares = Share::where('user_id', $user->id)->get();
|
||||
|
||||
$files = FileManagerFile::withTrashed()
|
||||
->where('user_id', $user->id)
|
||||
->get();
|
||||
$folders = FileManagerFolder::withTrashed()
|
||||
->where('user_id', $user->id)
|
||||
->get();
|
||||
|
||||
// Remove all files and thumbnails
|
||||
$files->each(function ($file) {
|
||||
|
||||
// Delete file
|
||||
Storage::delete('/file-manager/' . $file->basename);
|
||||
|
||||
// Delete thumbnail if exist
|
||||
if (!is_null($file->thumbnail)) {
|
||||
Storage::delete('/file-manager/' . $file->getRawOriginal('thumbnail'));
|
||||
}
|
||||
|
||||
// Delete file permanently
|
||||
$file->forceDelete();
|
||||
});
|
||||
|
||||
// Remove avatar
|
||||
if ($user->avatar) {
|
||||
Storage::delete('/avatars/' . $user->avatar);
|
||||
}
|
||||
|
||||
// Remove folders & shares
|
||||
$folders->each->forceDelete();
|
||||
$shares->each->forceDelete();
|
||||
|
||||
// Remove favourites
|
||||
$user->settings->delete();
|
||||
$user->favourite_folders()->sync([]);
|
||||
|
||||
// Delete user
|
||||
$user->delete();
|
||||
|
||||
return response('Done!', 204);
|
||||
}
|
||||
}
|
||||
@@ -1,248 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Content;
|
||||
use App\FileManagerFile;
|
||||
use App\FileManagerFolder;
|
||||
use App\Http\Requests\PublicPages\SendMessageRequest;
|
||||
use App\Http\Resources\PageResource;
|
||||
use App\Http\Tools\Demo;
|
||||
use App\Mail\SendSupportForm;
|
||||
use App\Page;
|
||||
use App\Setting;
|
||||
use App\User;
|
||||
use Artisan;
|
||||
use Doctrine\DBAL\Driver\PDOException;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Schema;
|
||||
|
||||
class AppFunctionsController extends Controller
|
||||
{
|
||||
/**
|
||||
* List of allowed settings to get from public request
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $whitelist = [
|
||||
'footer_content',
|
||||
'get_started_description',
|
||||
'get_started_title',
|
||||
'pricing_description',
|
||||
'pricing_title',
|
||||
'feature_description_3',
|
||||
'feature_title_3',
|
||||
'feature_description_2',
|
||||
'feature_title_2',
|
||||
'feature_description_1',
|
||||
'feature_title_1',
|
||||
'features_description',
|
||||
'features_title',
|
||||
'header_description',
|
||||
'header_title',
|
||||
'section_get_started',
|
||||
'section_pricing_content',
|
||||
'section_feature_boxes',
|
||||
'section_features',
|
||||
];
|
||||
|
||||
/**
|
||||
* Show index page
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
try {
|
||||
// Try to connect to database
|
||||
\DB::getPdo();
|
||||
|
||||
// Check settings table
|
||||
$settings_table = Schema::hasTable('settings');
|
||||
$users_table = Schema::hasTable('users');
|
||||
|
||||
// If settings table don't exist, then run migrations
|
||||
if ($users_table && !$settings_table) {
|
||||
Artisan::call('migrate', [
|
||||
'--force' => true
|
||||
]);
|
||||
}
|
||||
|
||||
// Get settings
|
||||
$upgraded = Setting::where('name', 'latest_upgrade')->first();
|
||||
|
||||
// Get connection string
|
||||
if ($upgraded && $upgraded->value !== '1.7') {
|
||||
$connection = 'quiet-update';
|
||||
} else if (!$upgraded) {
|
||||
$connection = 'quiet-update';
|
||||
} else {
|
||||
$connection = $this->get_setup_status();
|
||||
}
|
||||
|
||||
// Get all settings
|
||||
$settings = Setting::all();
|
||||
|
||||
// Get legal pages
|
||||
$legal = Page::whereIn('slug', ['terms-of-service', 'privacy-policy', 'cookie-policy'])
|
||||
->get(['visibility', 'title', 'slug']);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
$connection = 'setup-database';
|
||||
$settings = null;
|
||||
}
|
||||
|
||||
return view("index")
|
||||
->with('settings', $settings ? json_decode($settings->pluck('value', 'name')->toJson()) : null)
|
||||
->with('legal', isset($legal) ? $legal : null)
|
||||
->with('installation', $connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get og site for web crawlers
|
||||
*
|
||||
* @param $token
|
||||
*/
|
||||
public function og_site($token)
|
||||
{
|
||||
// Get all settings
|
||||
$settings = Setting::all();
|
||||
|
||||
// Get shared token
|
||||
$shared = get_shared($token);
|
||||
|
||||
// Get user
|
||||
$user = User::findOrFail($shared->user_id);
|
||||
|
||||
// Handle single file
|
||||
if ($shared->type === 'file') {
|
||||
|
||||
// Get file record
|
||||
$file = FileManagerFile::where('user_id', $shared->user_id)
|
||||
->where('unique_id', $shared->item_id)
|
||||
->first();
|
||||
|
||||
if ($file->thumbnail) {
|
||||
$file->setPublicUrl($token);
|
||||
}
|
||||
|
||||
$metadata = [
|
||||
'is_protected' => $shared->protected,
|
||||
'url' => url('/shared', ['token' => $token]),
|
||||
'user' => $user->name,
|
||||
'name' => $file->name,
|
||||
'size' => $file->filesize,
|
||||
'thumbnail' => $file->thumbnail ? $file->thumbnail : null,
|
||||
];
|
||||
}
|
||||
|
||||
// Handle single file
|
||||
if ($shared->type === 'folder') {
|
||||
|
||||
// Get file record
|
||||
$folder = FileManagerFolder::where('user_id', $shared->user_id)
|
||||
->where('unique_id', $shared->item_id)
|
||||
->first();
|
||||
|
||||
$metadata = [
|
||||
'is_protected' => $shared->protected,
|
||||
'url' => url('/shared', ['token' => $token]),
|
||||
'user' => $user->name,
|
||||
'name' => $folder->name,
|
||||
'size' => $folder->items,
|
||||
'thumbnail' => null,
|
||||
];
|
||||
}
|
||||
|
||||
// Return view
|
||||
return view("og-view")
|
||||
->with('settings', $settings)
|
||||
->with('metadata', $metadata);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if setup wizard was passed
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_setup_status(): string
|
||||
{
|
||||
$setup_success = get_setting('setup_wizard_success');
|
||||
|
||||
$connection = boolval($setup_success) ? 'setup-done' : 'setup-disclaimer';
|
||||
|
||||
return $connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send contact message from pages
|
||||
*
|
||||
* @param SendMessageRequest $request
|
||||
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function contact_form(SendMessageRequest $request)
|
||||
{
|
||||
// Get receiver email
|
||||
$receiver = Setting::where('name', 'contact_email')->first();
|
||||
|
||||
// Send message
|
||||
Mail::to($receiver->value)->send(new SendSupportForm($request->all()));
|
||||
|
||||
return response('Done', 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get single page content
|
||||
*
|
||||
* @param $slug
|
||||
* @return PageResource
|
||||
*/
|
||||
public function get_page($slug)
|
||||
{
|
||||
return new PageResource(
|
||||
Page::where('slug', $slug)->first()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get selected settings from public route
|
||||
*
|
||||
* @param Request $request
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_settings(Request $request)
|
||||
{
|
||||
$column = $request->get('column');
|
||||
|
||||
if (strpos($column, '|') !== false) {
|
||||
|
||||
$columns = collect(explode('|', $column));
|
||||
|
||||
$columns->each(function ($column) {
|
||||
if (!in_array($column, $this->whitelist)) abort(401);
|
||||
});
|
||||
|
||||
return Setting::whereIn('name', $columns)->pluck('value', 'name');
|
||||
}
|
||||
|
||||
if (!in_array($column, $this->whitelist)) abort(401);
|
||||
|
||||
return Setting::where('name', $column)->pluck('value', 'name');
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear application cache
|
||||
*/
|
||||
public function flush_cache()
|
||||
{
|
||||
// Check if is demo
|
||||
if (env('APP_DEMO')) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
Artisan::call('cache:clear');
|
||||
Artisan::call('config:clear');
|
||||
Artisan::call('config:cache');
|
||||
}
|
||||
}
|
||||
@@ -1,147 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Requests\Auth\CheckAccountRequest;
|
||||
use App\Setting;
|
||||
use App\User;
|
||||
use App\UserSettings;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
class AuthController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Check if user account exist
|
||||
*
|
||||
* @param Request $request
|
||||
* @return mixed
|
||||
*/
|
||||
public function check_account(CheckAccountRequest $request)
|
||||
{
|
||||
// Get User
|
||||
$user = User::where('email', $request->input('email'))->select(['name', 'avatar'])->first();
|
||||
|
||||
// Return user info
|
||||
if ($user) return [
|
||||
'name' => $user->name,
|
||||
'avatar' => $user->avatar,
|
||||
];
|
||||
|
||||
// Abort with 404, user not found
|
||||
return abort('404', __('vuefilemanager.user_not_fount'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Login user
|
||||
*
|
||||
* @param Request $request
|
||||
* @return mixed
|
||||
*/
|
||||
public function login(Request $request)
|
||||
{
|
||||
$response = Route::dispatch(self::make_login_request($request));
|
||||
|
||||
if ($response->isSuccessful()) {
|
||||
|
||||
$data = json_decode($response->content(), true);
|
||||
|
||||
return response('Login Successfull!', 200)->cookie('access_token', $data['access_token'], 43200);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register user
|
||||
*
|
||||
* @param Request $request
|
||||
* @return mixed
|
||||
*/
|
||||
public function register(Request $request)
|
||||
{
|
||||
$settings = Setting::whereIn('name', ['storage_default', 'registration'])->pluck('value', 'name');
|
||||
|
||||
// Check if account registration is enabled
|
||||
if (! intval($settings['registration'])) abort(401);
|
||||
|
||||
// Validate request
|
||||
$request->validate([
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
|
||||
'password' => ['required', 'string', 'min:6', 'confirmed'],
|
||||
]);
|
||||
|
||||
// Create user
|
||||
$user = User::create([
|
||||
'name' => $request->name,
|
||||
'email' => $request->email,
|
||||
'password' => Hash::make($request->password),
|
||||
]);
|
||||
|
||||
// Create settings
|
||||
UserSettings::forceCreate([
|
||||
'user_id' => $user->id,
|
||||
'storage_capacity' => $settings['storage_default'],
|
||||
]);
|
||||
|
||||
$response = Route::dispatch(self::make_login_request($request));
|
||||
|
||||
if ($response->isSuccessful()) {
|
||||
|
||||
$data = json_decode($response->content(), true);
|
||||
|
||||
return response('Register Successfull!', 200)->cookie('access_token', $data['access_token'], 43200);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logout user entity
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function logout()
|
||||
{
|
||||
// Demo preview
|
||||
if (is_demo(Auth::id())) {
|
||||
return response('Logout successfull', 204)
|
||||
->cookie('access_token', '', -1);
|
||||
}
|
||||
|
||||
// Get user tokens and remove it
|
||||
auth()->user()->tokens()->each(function ($token) {
|
||||
|
||||
// Remove tokens
|
||||
$token->delete();
|
||||
});
|
||||
|
||||
return response('Logout successful', 204)
|
||||
->cookie('access_token', '', -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make login request for get access token
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Request
|
||||
*/
|
||||
private static function make_login_request($request)
|
||||
{
|
||||
$request->request->add([
|
||||
'grant_type' => 'password',
|
||||
'client_id' => config('services.passport.client_id'),
|
||||
'client_secret' => config('services.passport.client_secret'),
|
||||
'username' => $request->email,
|
||||
'password' => $request->password,
|
||||
'scope' => 'master',
|
||||
]);
|
||||
|
||||
return Request::create(url('/oauth/token'), 'POST', $request->all());
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use App\User;
|
||||
use Illuminate\Foundation\Auth\RegistersUsers;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
class RegisterController extends Controller
|
||||
{
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Register Controller
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This controller handles the registration of new users as well as their
|
||||
| validation and creation. By default this controller uses a trait to
|
||||
| provide this functionality without requiring any additional code.
|
||||
|
|
||||
*/
|
||||
|
||||
use RegistersUsers;
|
||||
|
||||
/**
|
||||
* Where to redirect users after registration.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $redirectTo = RouteServiceProvider::HOME;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('guest');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a validator for an incoming registration request.
|
||||
*
|
||||
* @param array $data
|
||||
* @return \Illuminate\Contracts\Validation\Validator
|
||||
*/
|
||||
protected function validator(array $data)
|
||||
{
|
||||
return Validator::make($data, [
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
|
||||
'password' => ['required', 'string', 'min:8', 'confirmed'],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new user instance after a valid registration.
|
||||
*
|
||||
* @param array $data
|
||||
* @return \App\User
|
||||
*/
|
||||
protected function create(array $data)
|
||||
{
|
||||
return User::create([
|
||||
'name' => $data['name'],
|
||||
'email' => $data['email'],
|
||||
'password' => Hash::make($data['password']),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Artisan;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\UnauthorizedException;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
|
||||
class DeployController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get web hook payload and verify request
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function github(Request $request) {
|
||||
|
||||
if (($signature = $request->headers->get('X-Hub-Signature')) == null) {
|
||||
throw new BadRequestHttpException('Header not set');
|
||||
}
|
||||
|
||||
$signature_parts = explode('=', $signature);
|
||||
|
||||
if (count($signature_parts) != 2) {
|
||||
throw new BadRequestHttpException('signature has invalid format');
|
||||
}
|
||||
|
||||
$known_signature = hash_hmac('sha1', $request->getContent(), config('app.deploy_secret'));
|
||||
|
||||
if (! hash_equals($known_signature, $signature_parts[1])) {
|
||||
throw new UnauthorizedException('Could not verify request signature ' . $signature_parts[1]);
|
||||
}
|
||||
|
||||
// Run deploying
|
||||
Artisan::call('deploy:production');
|
||||
|
||||
Log::info('The GitHub webhook was accepted');
|
||||
|
||||
return response('The GitHub webhook was accepted', 202);
|
||||
}
|
||||
}
|
||||
@@ -1,235 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\FileManagerFolder;
|
||||
use App\Http\Tools\Guardian;
|
||||
use App\Share;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Http\Request;
|
||||
use App\FileManagerFile;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Response;
|
||||
|
||||
class FileAccessController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get avatar
|
||||
*
|
||||
* @param $basename
|
||||
* @return mixed
|
||||
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
|
||||
*/
|
||||
public function get_avatar($basename)
|
||||
{
|
||||
// Get file path
|
||||
$path = '/avatars/' . $basename;
|
||||
|
||||
// Check if file exist
|
||||
if (!Storage::exists($path)) abort(404);
|
||||
|
||||
// Return avatar
|
||||
return Storage::download($path, $basename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get system image
|
||||
*
|
||||
* @param $basename
|
||||
* @return mixed
|
||||
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
|
||||
*/
|
||||
public function get_system_image($basename)
|
||||
{
|
||||
// Get file path
|
||||
$path = '/system/' . $basename;
|
||||
|
||||
// Check if file exist
|
||||
if (!Storage::exists($path)) abort(404);
|
||||
|
||||
// Return avatar
|
||||
return Storage::download($path, $basename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file
|
||||
*
|
||||
* @param Request $request
|
||||
* @param $filename
|
||||
* @return mixed
|
||||
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
|
||||
*/
|
||||
public function get_file(Request $request, $filename)
|
||||
{
|
||||
// Get user id
|
||||
$user_id = Auth::id();
|
||||
|
||||
// Get file record
|
||||
$file = FileManagerFile::withTrashed()
|
||||
->where('user_id', $user_id)
|
||||
->where('basename', $filename)
|
||||
->firstOrFail();
|
||||
|
||||
// Check user permission
|
||||
if (!$request->user()->tokenCan('master')) {
|
||||
|
||||
// Get shared token
|
||||
$shared = get_shared($request->cookie('shared_token'));
|
||||
|
||||
// Check access to file
|
||||
$this->check_file_access($shared, $file);
|
||||
}
|
||||
|
||||
return $this->download_file($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file public
|
||||
*
|
||||
* @param $filename
|
||||
* @param $token
|
||||
* @return mixed
|
||||
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
|
||||
*/
|
||||
public function get_file_public($filename, $token)
|
||||
{
|
||||
// Get sharing record
|
||||
$shared = get_shared($token);
|
||||
|
||||
// Abort if shared is protected
|
||||
if ((int) $shared->protected) {
|
||||
abort(403, "Sorry, you don't have permission");
|
||||
}
|
||||
|
||||
// Get file record
|
||||
$file = FileManagerFile::where('user_id', $shared->user_id)
|
||||
->where('basename', $filename)
|
||||
->firstOrFail();
|
||||
|
||||
// Check file access
|
||||
$this->check_file_access($shared, $file);
|
||||
|
||||
return $this->download_file($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image thumbnail
|
||||
*
|
||||
* @param Request $request
|
||||
* @param $filename
|
||||
* @return mixed
|
||||
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
|
||||
*/
|
||||
public function get_thumbnail(Request $request, $filename)
|
||||
{
|
||||
// Get file record
|
||||
$file = FileManagerFile::withTrashed()
|
||||
->where('user_id', $request->user()->id)
|
||||
->where('thumbnail', $filename)
|
||||
->firstOrFail();
|
||||
|
||||
// Check user permission
|
||||
if (!$request->user()->tokenCan('master')) {
|
||||
$this->check_file_access($request, $file);
|
||||
}
|
||||
|
||||
return $this->thumbnail_file($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get public image thumbnail
|
||||
*
|
||||
* @param $filename
|
||||
* @param $token
|
||||
* @return mixed
|
||||
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
|
||||
*/
|
||||
public function get_thumbnail_public($filename, $token)
|
||||
{
|
||||
// Get sharing record
|
||||
$shared = get_shared($token);
|
||||
|
||||
// Abort if thumbnail is protected
|
||||
if ((int) $shared->protected) {
|
||||
abort(403, "Sorry, you don't have permission");
|
||||
}
|
||||
|
||||
// Get file record
|
||||
$file = FileManagerFile::where('user_id', $shared->user_id)
|
||||
->where('thumbnail', $filename)
|
||||
->firstOrFail();
|
||||
|
||||
// Check file access
|
||||
$this->check_file_access($shared, $file);
|
||||
|
||||
return $this->thumbnail_file($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check user file access
|
||||
*
|
||||
* @param $shared
|
||||
* @param $file
|
||||
*/
|
||||
protected function check_file_access($shared, $file): void
|
||||
{
|
||||
// Check by parent folder permission
|
||||
if ($shared->type === 'folder') {
|
||||
Guardian::check_item_access($file->folder_id, $shared);
|
||||
}
|
||||
|
||||
// Check by single file permission
|
||||
if ($shared->type === 'file') {
|
||||
if ($shared->item_id !== $file->unique_id) abort(403);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call and download file
|
||||
*
|
||||
* @param $file
|
||||
* @return mixed
|
||||
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
|
||||
*/
|
||||
private function download_file($file)
|
||||
{
|
||||
$file_pretty_name = get_pretty_name($file->basename, $file->name, $file->mimetype);
|
||||
|
||||
// Get file path
|
||||
$path = '/file-manager/' . $file->basename;
|
||||
|
||||
// Check if file exist
|
||||
if (!Storage::exists($path)) abort(404);
|
||||
|
||||
$header = [
|
||||
"Content-Type" => Storage::mimeType($path),
|
||||
"Content-Length" => Storage::size($path),
|
||||
"Accept-Ranges" => "bytes",
|
||||
"Content-Range" => "bytes 0-600/" . Storage::size($path),
|
||||
];
|
||||
|
||||
// Get file
|
||||
return Storage::download($path, $file_pretty_name, $header);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $file
|
||||
* @return mixed
|
||||
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
|
||||
*/
|
||||
private function thumbnail_file($file)
|
||||
{
|
||||
// Get file path
|
||||
$path = '/file-manager/' . $file->getRawOriginal('thumbnail');
|
||||
|
||||
// Check if file exist
|
||||
if (!Storage::exists($path)) abort(404);
|
||||
|
||||
// Return image thumbnail
|
||||
return Storage::download($path, $file->getRawOriginal('thumbnail'));
|
||||
}
|
||||
}
|
||||
@@ -1,225 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\FileBrowser;
|
||||
|
||||
use App\Http\Requests\FileBrowser\SearchRequest;
|
||||
use App\User;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Http\Request;
|
||||
use App\FileManagerFolder;
|
||||
use App\FileManagerFile;
|
||||
use App\Share;
|
||||
|
||||
class BrowseController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Get trashed files
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function trash()
|
||||
{
|
||||
// Get user id
|
||||
$user_id = Auth::id();
|
||||
|
||||
// Get folders and files
|
||||
$folders_trashed = FileManagerFolder::onlyTrashed()
|
||||
->with(['trashed_folders', 'parent'])
|
||||
->where('user_id', $user_id)
|
||||
->get(['parent_id', 'unique_id', 'name']);
|
||||
|
||||
$folders = FileManagerFolder::onlyTrashed()
|
||||
->with(['parent'])
|
||||
->where('user_id', $user_id)
|
||||
->whereIn('unique_id', filter_folders_ids($folders_trashed))
|
||||
->get();
|
||||
|
||||
// Get files trashed
|
||||
$files_trashed = FileManagerFile::onlyTrashed()
|
||||
->with(['parent'])
|
||||
->where('user_id', $user_id)
|
||||
->whereNotIn('folder_id', array_values(array_unique(recursiveFind($folders_trashed->toArray(), 'unique_id'))))
|
||||
->get();
|
||||
|
||||
// Collect folders and files to single array
|
||||
return collect([$folders, $files_trashed])->collapse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user shared items
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function shared()
|
||||
{
|
||||
// Get user
|
||||
$user_id = Auth::id();
|
||||
|
||||
// Get shared folders and files
|
||||
$folder_ids = Share::where('user_id', $user_id)
|
||||
->where('type', 'folder')
|
||||
->pluck('item_id');
|
||||
|
||||
$file_ids = Share::where('user_id', $user_id)
|
||||
->where('type', '!=', 'folder')
|
||||
->pluck('item_id');
|
||||
|
||||
// Get folders and files
|
||||
$folders = FileManagerFolder::with(['parent', 'shared:token,id,item_id,permission,protected'])
|
||||
->where('user_id', $user_id)
|
||||
->whereIn('unique_id', $folder_ids)
|
||||
->get();
|
||||
|
||||
$files = FileManagerFile::with(['parent', 'shared:token,id,item_id,permission,protected'])
|
||||
->where('user_id', $user_id)
|
||||
->whereIn('unique_id', $file_ids)
|
||||
->get();
|
||||
|
||||
// Collect folders and files to single array
|
||||
return collect([$folders, $files])->collapse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get latest user uploads
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function latest() {
|
||||
|
||||
// Get User
|
||||
$user = User::with(['latest_uploads'])
|
||||
->where('id', Auth::id())
|
||||
->first();
|
||||
|
||||
return $user->latest_uploads->makeHidden(['user_id', 'basename']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get participant uploads
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function participant_uploads() {
|
||||
|
||||
// Get User
|
||||
$uploads = FileManagerFile::with(['parent'])->where('user_id', Auth::id())
|
||||
->whereUserScope('editor')->orderBy('created_at', 'DESC')->get();
|
||||
|
||||
return $uploads;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get directory with files
|
||||
*
|
||||
* @param Request $request
|
||||
* @param $unique_id
|
||||
* @return Collection
|
||||
*/
|
||||
public function folder(Request $request, $unique_id)
|
||||
{
|
||||
// Get user
|
||||
$user_id = Auth::id();
|
||||
|
||||
// Get folder trash items
|
||||
if ($request->query('trash')) {
|
||||
|
||||
// Get folders and files
|
||||
$folders = FileManagerFolder::onlyTrashed()
|
||||
->with('parent')
|
||||
->where('user_id', $user_id)
|
||||
->where('parent_id', $unique_id)
|
||||
->get();
|
||||
|
||||
$files = FileManagerFile::onlyTrashed()
|
||||
->with('parent')
|
||||
->where('user_id', $user_id)
|
||||
->where('folder_id', $unique_id)
|
||||
->get();
|
||||
|
||||
// Collect folders and files to single array
|
||||
return collect([$folders, $files])->collapse();
|
||||
}
|
||||
|
||||
// Get folders and files
|
||||
$folders = FileManagerFolder::with(['parent', 'shared:token,id,item_id,permission,protected'])
|
||||
->where('user_id', $user_id)
|
||||
->where('parent_id', $unique_id)
|
||||
->orderBy('created_at', 'DESC')
|
||||
->get();
|
||||
|
||||
$files = FileManagerFile::with(['parent', 'shared:token,id,item_id,permission,protected'])
|
||||
->where('user_id', $user_id)
|
||||
->where('folder_id', $unique_id)
|
||||
->orderBy('created_at', 'DESC')
|
||||
->get();
|
||||
|
||||
// Collect folders and files to single array
|
||||
return collect([$folders, $files])->collapse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user folder tree
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function navigation_tree() {
|
||||
|
||||
$folders = FileManagerFolder::with('folders:id,parent_id,unique_id,name')
|
||||
->where('parent_id', 0)
|
||||
->where('user_id', Auth::id())
|
||||
->get(['id', 'parent_id', 'unique_id', 'name']);
|
||||
|
||||
return [
|
||||
[
|
||||
'unique_id' => 0,
|
||||
'name' => __('vuefilemanager.home'),
|
||||
'location' => 'base',
|
||||
'folders' => $folders,
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Search files
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function search(SearchRequest $request)
|
||||
{
|
||||
// Get user
|
||||
$user_id = Auth::id();
|
||||
|
||||
// Search files id db
|
||||
$searched_files = FileManagerFile::search($request->input('query'))
|
||||
->where('user_id', $user_id)
|
||||
->get();
|
||||
$searched_folders = FileManagerFolder::search($request->input('query'))
|
||||
->where('user_id', $user_id)
|
||||
->get();
|
||||
|
||||
// Collect folders and files to single array
|
||||
return collect([$searched_folders, $searched_files])->collapse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file record
|
||||
*
|
||||
* @param $unique_id
|
||||
* @return mixed
|
||||
*/
|
||||
public function file_detail($unique_id)
|
||||
{
|
||||
// Get user id
|
||||
$user_id = Auth::id();
|
||||
|
||||
return FileManagerFile::with(['shared:token,id,item_id,permission,protected'])
|
||||
->where('user_id', $user_id)
|
||||
->where('unique_id', $unique_id)
|
||||
->firstOrFail();
|
||||
}
|
||||
}
|
||||
@@ -1,385 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\FileFunctions;
|
||||
|
||||
use App\Http\Requests\FileFunctions\CreateFolderRequest;
|
||||
use App\Http\Requests\FileFunctions\DeleteItemRequest;
|
||||
use App\Http\Requests\FileFunctions\RenameItemRequest;
|
||||
use App\Http\Requests\FileFunctions\MoveItemRequest;
|
||||
use App\Http\Requests\FileFunctions\UploadRequest;
|
||||
use App\Http\Tools\Demo;
|
||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Tools\Guardian;
|
||||
use App\Http\Tools\Editor;
|
||||
use App\FileManagerFile;
|
||||
use Exception;
|
||||
|
||||
|
||||
class EditItemsController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create new folder for authenticated master|editor user
|
||||
*
|
||||
* @param CreateFolderRequest $request
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
public function user_create_folder(CreateFolderRequest $request)
|
||||
{
|
||||
// Demo preview
|
||||
if (is_demo(Auth::id())) {
|
||||
return Demo::create_folder($request);
|
||||
}
|
||||
|
||||
// Check permission to create folder for authenticated editor
|
||||
if ($request->user()->tokenCan('editor')) {
|
||||
|
||||
// check if shared_token cookie exist
|
||||
if (!$request->hasCookie('shared_token')) abort('401');
|
||||
|
||||
// Get shared token
|
||||
$shared = get_shared($request->cookie('shared_token'));
|
||||
|
||||
// Check access to requested directory
|
||||
Guardian::check_item_access($request->parent_id, $shared);
|
||||
}
|
||||
|
||||
// Create new folder
|
||||
return Editor::create_folder($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new folder for guest user with edit permission
|
||||
*
|
||||
* @param CreateFolderRequest $request
|
||||
* @param $token
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
public function guest_create_folder(CreateFolderRequest $request, $token)
|
||||
{
|
||||
// Get shared record
|
||||
$shared = get_shared($token);
|
||||
|
||||
if (is_demo($shared->user_id)) {
|
||||
return Demo::create_folder($request);
|
||||
}
|
||||
|
||||
// Check shared permission
|
||||
if (!is_editor($shared)) abort(403);
|
||||
|
||||
// Check access to requested directory
|
||||
Guardian::check_item_access($request->parent_id, $shared);
|
||||
|
||||
// Create folder
|
||||
return Editor::create_folder($request, $shared);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename item for authenticated master|editor user
|
||||
*
|
||||
* @param RenameItemRequest $request
|
||||
* @param $unique_id
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function user_rename_item(RenameItemRequest $request, $unique_id)
|
||||
{
|
||||
// Demo preview
|
||||
if (is_demo(Auth::id())) {
|
||||
return Demo::rename_item($request, $unique_id);
|
||||
}
|
||||
|
||||
// Check permission to rename item for authenticated editor
|
||||
if ($request->user()->tokenCan('editor')) {
|
||||
|
||||
// check if shared_token cookie exist
|
||||
if (!$request->hasCookie('shared_token')) abort('401');
|
||||
|
||||
// Get shared token
|
||||
$shared = get_shared($request->cookie('shared_token'));
|
||||
|
||||
// Get file|folder item
|
||||
$item = get_item($request->type, $unique_id, Auth::id());
|
||||
|
||||
// Check access to requested directory
|
||||
if ($request->type === 'folder') {
|
||||
Guardian::check_item_access($item->unique_id, $shared);
|
||||
} else {
|
||||
Guardian::check_item_access($item->folder_id, $shared);
|
||||
}
|
||||
}
|
||||
|
||||
// Rename Item
|
||||
return Editor::rename_item($request, $unique_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename item for guest user with edit permission
|
||||
*
|
||||
* @param RenameItemRequest $request
|
||||
* @param $unique_id
|
||||
* @param $token
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function guest_rename_item(RenameItemRequest $request, $unique_id, $token)
|
||||
{
|
||||
// Get shared record
|
||||
$shared = get_shared($token);
|
||||
|
||||
// Demo preview
|
||||
if (is_demo($shared->user_id)) {
|
||||
return Demo::rename_item($request, $unique_id);
|
||||
}
|
||||
|
||||
// Check shared permission
|
||||
if (!is_editor($shared)) abort(403);
|
||||
|
||||
// Get file|folder item
|
||||
$item = get_item($request->type, $unique_id, $shared->user_id);
|
||||
|
||||
// Check access to requested item
|
||||
if ($request->type === 'folder') {
|
||||
Guardian::check_item_access($item->unique_id, $shared);
|
||||
} else {
|
||||
Guardian::check_item_access($item->folder_id, $shared);
|
||||
}
|
||||
|
||||
// Rename item
|
||||
$item = Editor::rename_item($request, $unique_id, $shared);
|
||||
|
||||
// Set public url
|
||||
if ($item->type !== 'folder') {
|
||||
$item->setPublicUrl($token);
|
||||
}
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete item for authenticated master|editor user
|
||||
*
|
||||
* @param DeleteItemRequest $request
|
||||
* @param $unique_id
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
* @throws Exception
|
||||
*/
|
||||
public function user_delete_item(DeleteItemRequest $request, $unique_id)
|
||||
{
|
||||
// Demo preview
|
||||
if (is_demo(Auth::id())) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Check permission to delete item for authenticated editor
|
||||
if ($request->user()->tokenCan('editor')) {
|
||||
|
||||
// Prevent force delete for non-master users
|
||||
if ($request->input('data.force_delete')) abort('401');
|
||||
|
||||
// check if shared_token cookie exist
|
||||
if (!$request->hasCookie('shared_token')) abort('401');
|
||||
|
||||
// Get shared token
|
||||
$shared = get_shared($request->cookie('shared_token'));
|
||||
|
||||
// Get file|folder item
|
||||
$item = get_item($request->input('data.type'), $unique_id, Auth::id());
|
||||
|
||||
// Check access to requested directory
|
||||
if ($request->input('data.type') === 'folder') {
|
||||
Guardian::check_item_access($item->unique_id, $shared);
|
||||
} else {
|
||||
Guardian::check_item_access($item->folder_id, $shared);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete item
|
||||
Editor::delete_item($request, $unique_id);
|
||||
|
||||
// Return response
|
||||
return response(null, 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete item for guest user with edit permission
|
||||
*
|
||||
* @param DeleteItemRequest $request
|
||||
* @param $unique_id
|
||||
* @param $token
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
* @throws Exception
|
||||
*/
|
||||
public function guest_delete_item(DeleteItemRequest $request, $unique_id, $token)
|
||||
{
|
||||
// Get shared record
|
||||
$shared = get_shared($token);
|
||||
|
||||
// Demo preview
|
||||
if (is_demo($shared->user_id)) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Check shared permission
|
||||
if (!is_editor($shared)) abort(403);
|
||||
|
||||
// Get file|folder item
|
||||
$item = get_item($request->input('data.type'), $unique_id, $shared->user_id);
|
||||
|
||||
// Check access to requested item
|
||||
if ($request->input('data.type') === 'folder') {
|
||||
Guardian::check_item_access($item->unique_id, $shared);
|
||||
} else {
|
||||
Guardian::check_item_access($item->folder_id, $shared);
|
||||
}
|
||||
|
||||
// Delete item
|
||||
Editor::delete_item($request, $unique_id, $shared);
|
||||
|
||||
// Return response
|
||||
return response(null, 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload file for authenticated master|editor user
|
||||
*
|
||||
* @param UploadRequest $request
|
||||
* @return FileManagerFile|Model
|
||||
* @throws Exception
|
||||
*/
|
||||
public function user_upload(UploadRequest $request)
|
||||
{
|
||||
// Demo preview
|
||||
if (is_demo(Auth::id())) {
|
||||
return Demo::upload($request);
|
||||
}
|
||||
|
||||
// Check permission to upload for authenticated editor
|
||||
if ($request->user()->tokenCan('editor')) {
|
||||
|
||||
// check if shared_token cookie exist
|
||||
if (!$request->hasCookie('shared_token')) abort('401');
|
||||
|
||||
// Get shared token
|
||||
$shared = get_shared($request->cookie('shared_token'));
|
||||
|
||||
// Check access to requested directory
|
||||
Guardian::check_item_access($request->parent_id, $shared);
|
||||
}
|
||||
|
||||
// Return new uploaded file
|
||||
return Editor::upload($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete file for guest user with edit permission
|
||||
*
|
||||
* @param UploadRequest $request
|
||||
* @param $token
|
||||
* @return FileManagerFile|Model
|
||||
* @throws Exception
|
||||
*/
|
||||
public function guest_upload(UploadRequest $request, $token)
|
||||
{
|
||||
// Get shared record
|
||||
$shared = get_shared($token);
|
||||
|
||||
// Demo preview
|
||||
if (is_demo($shared->user_id)) {
|
||||
return Demo::upload($request);
|
||||
}
|
||||
|
||||
// Check shared permission
|
||||
if (!is_editor($shared)) abort(403);
|
||||
|
||||
// Check access to requested directory
|
||||
Guardian::check_item_access($request->parent_id, $shared);
|
||||
|
||||
// Return new uploaded file
|
||||
$new_file = Editor::upload($request, $shared);
|
||||
|
||||
// Set public access url
|
||||
$new_file->setPublicUrl($token);
|
||||
|
||||
return $new_file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move item for authenticated master|editor user
|
||||
*
|
||||
* @param MoveItemRequest $request
|
||||
* @param $unique_id
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function user_move(MoveItemRequest $request, $unique_id)
|
||||
{
|
||||
// Demo preview
|
||||
if (is_demo(Auth::id())) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Check permission to upload for authenticated editor
|
||||
if ($request->user()->tokenCan('editor')) {
|
||||
|
||||
// check if shared_token cookie exist
|
||||
if (!$request->hasCookie('shared_token')) abort('401');
|
||||
|
||||
// Get shared token
|
||||
$shared = get_shared($request->cookie('shared_token'));
|
||||
|
||||
// Check access to requested directory
|
||||
Guardian::check_item_access($request->to_unique_id, $shared);
|
||||
}
|
||||
|
||||
// Move item
|
||||
Editor::move($request, $unique_id);
|
||||
|
||||
return response('Done!', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move item for guest user with edit permission
|
||||
*
|
||||
* @param MoveItemRequest $request
|
||||
* @param $unique_id
|
||||
* @param $token
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function guest_move(MoveItemRequest $request, $unique_id, $token)
|
||||
{
|
||||
// Get shared record
|
||||
$shared = get_shared($token);
|
||||
|
||||
// Demo preview
|
||||
if (is_demo(Auth::id())) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Check shared permission
|
||||
if (!is_editor($shared)) abort(403);
|
||||
|
||||
$moving_unique_id = $unique_id;
|
||||
|
||||
if ($request->from_type !== 'folder') {
|
||||
$file = FileManagerFile::where('unique_id', $unique_id)
|
||||
->where('user_id', $shared->user_id)
|
||||
->firstOrFail();
|
||||
|
||||
$moving_unique_id = $file->folder_id;
|
||||
}
|
||||
|
||||
// Check access to requested item
|
||||
Guardian::check_item_access([
|
||||
$request->to_unique_id, $moving_unique_id
|
||||
], $shared);
|
||||
|
||||
// Move item
|
||||
Editor::move($request, $unique_id, $shared);
|
||||
|
||||
return response('Done!', 204);
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\FileFunctions;
|
||||
|
||||
use App\FileManagerFolder;
|
||||
use App\Http\Tools\Demo;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class FavouriteController extends Controller
|
||||
{
|
||||
/**
|
||||
* Add folder to user favourites
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
// Validate request
|
||||
$validator = Validator::make($request->all(), [
|
||||
'unique_id' => 'required|integer',
|
||||
]);
|
||||
|
||||
// Return error
|
||||
if ($validator->fails()) abort(400, 'Bad input');
|
||||
|
||||
// Get user & folder
|
||||
$user = Auth::user();
|
||||
$folder = FileManagerFolder::where('unique_id', $request->unique_id)->first();
|
||||
|
||||
if (is_demo($user->id)) {
|
||||
return Demo::favourites($user);
|
||||
}
|
||||
|
||||
// Check ownership
|
||||
if ($folder->user_id !== $user->id) abort(403);
|
||||
|
||||
// Add folder to user favourites
|
||||
$user->favourite_folders()->syncWithoutDetaching($request->unique_id);
|
||||
|
||||
// Return updated favourites
|
||||
return $user->favourite_folders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove folder from user favourites
|
||||
*
|
||||
* @param $unique_id
|
||||
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy($unique_id)
|
||||
{
|
||||
// Get user
|
||||
$user = Auth::user();
|
||||
|
||||
if (is_demo($user->id)) {
|
||||
return Demo::favourites($user);
|
||||
}
|
||||
|
||||
// Remove folder from user favourites
|
||||
$user->favourite_folders()->detach($unique_id);
|
||||
|
||||
// Return updated favourites
|
||||
return $user->favourite_folders;
|
||||
}
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\FileFunctions;
|
||||
|
||||
use App\Http\Requests\Share\CreateShareRequest;
|
||||
use App\Http\Requests\Share\UpdateShareRequest;
|
||||
use App\Http\Resources\ShareResource;
|
||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Str;
|
||||
use App\Share;
|
||||
|
||||
class ShareController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get shared record
|
||||
*
|
||||
* @return ShareResource
|
||||
*/
|
||||
public function show($token)
|
||||
{
|
||||
// Get record
|
||||
$shared = Share::where(DB::raw('BINARY `token`'), $token)
|
||||
->firstOrFail();
|
||||
|
||||
return new ShareResource($shared);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate file share link
|
||||
*
|
||||
* @param CreateShareRequest $request
|
||||
* @return ShareResource
|
||||
*/
|
||||
public function store(CreateShareRequest $request)
|
||||
{
|
||||
do {
|
||||
// Generate unique token
|
||||
$token = Str::random(16);
|
||||
|
||||
} while (Share::where(DB::raw('BINARY `token`'), $token)->exists());
|
||||
|
||||
// Create shared options
|
||||
$options = [
|
||||
'password' => $request->has('password') ? Hash::make($request->password) : null,
|
||||
'type' => $request->type === 'folder' ? 'folder' : 'file',
|
||||
'protected' => $request->isPassword,
|
||||
'permission' => $request->permission,
|
||||
'item_id' => $request->unique_id,
|
||||
'user_id' => Auth::id(),
|
||||
'token' => $token,
|
||||
];
|
||||
|
||||
// Return created shared record
|
||||
return new ShareResource(Share::create($options));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update sharing
|
||||
*
|
||||
* @param UpdateShareRequest $request
|
||||
* @param $token
|
||||
* @return ShareResource
|
||||
*/
|
||||
public function update(UpdateShareRequest $request, $token)
|
||||
{
|
||||
// Get sharing record
|
||||
$shared = Share::where('token', $token)
|
||||
->where('user_id', Auth::id())
|
||||
->firstOrFail();
|
||||
|
||||
// Update sharing record
|
||||
$shared->update([
|
||||
'permission' => $request->permission,
|
||||
'protected' => $request->protected,
|
||||
'password' => $request->password ? Hash::make($request->password) : $shared->password,
|
||||
]);
|
||||
|
||||
// Return shared record
|
||||
return new ShareResource($shared);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete sharing item
|
||||
*
|
||||
* @param $token
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function destroy($token)
|
||||
{
|
||||
// Get sharing record
|
||||
$shared = Share::where('token', $token)
|
||||
->where('user_id', Auth::id())
|
||||
->firstOrFail();
|
||||
|
||||
// Delete shared record
|
||||
$shared->delete();
|
||||
|
||||
// Done
|
||||
return response('Done!', 204);
|
||||
}
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\FileFunctions;
|
||||
|
||||
use App\Http\Tools\Demo;
|
||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Http\Request;
|
||||
use App\FileManagerFolder;
|
||||
use App\FileManagerFile;
|
||||
|
||||
class TrashController extends Controller
|
||||
{
|
||||
/**
|
||||
* Empty user trash
|
||||
*
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
// Get user id
|
||||
$user_id = Auth::id();
|
||||
|
||||
if (is_demo($user_id)) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Get files and folders
|
||||
$folders = FileManagerFolder::onlyTrashed()->where('user_id', $user_id)->get();
|
||||
$files = FileManagerFile::onlyTrashed()->where('user_id', $user_id)->get();
|
||||
|
||||
// Force delete folder
|
||||
$folders->each->forceDelete();
|
||||
|
||||
// Force delete files
|
||||
foreach ($files as $file) {
|
||||
|
||||
// Delete file
|
||||
Storage::delete('/file-manager/' . $file->basename);
|
||||
|
||||
// Delete thumbnail if exist
|
||||
if ($file->thumbnail) Storage::delete('/file-manager/' . $file->getRawOriginal('thumbnail'));
|
||||
|
||||
// Delete file permanently
|
||||
$file->forceDelete();
|
||||
}
|
||||
|
||||
// Return response
|
||||
return response('Done!', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore item from trash
|
||||
*
|
||||
* @param Request $request
|
||||
* @param $unique_id
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function restore(Request $request, $unique_id)
|
||||
{
|
||||
// Validate request
|
||||
$validator = Validator::make($request->all(), [
|
||||
'type' => 'required|string',
|
||||
'to_home' => 'boolean',
|
||||
]);
|
||||
|
||||
// Return error
|
||||
if ($validator->fails()) abort(400, 'Bad input');
|
||||
|
||||
// Get user id
|
||||
$user_id = Auth::id();
|
||||
|
||||
if (is_demo($user_id)) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Get folder
|
||||
if ($request->type === 'folder') {
|
||||
|
||||
// Get folder
|
||||
$item = FileManagerFolder::onlyTrashed()
|
||||
->where('user_id', $user_id)
|
||||
->where('unique_id', $unique_id)
|
||||
->first();
|
||||
|
||||
// Restore item to home directory
|
||||
if ($request->has('to_home') && $request->to_home) {
|
||||
$item->parent_id = 0;
|
||||
$item->save();
|
||||
}
|
||||
} else {
|
||||
|
||||
// Get item
|
||||
$item = FileManagerFile::onlyTrashed()
|
||||
->where('user_id', $user_id)
|
||||
->where('unique_id', $unique_id)
|
||||
->first();
|
||||
|
||||
// Restore item to home directory
|
||||
if ($request->has('to_home') && $request->to_home) {
|
||||
$item->folder_id = 0;
|
||||
$item->save();
|
||||
}
|
||||
}
|
||||
|
||||
// Restore Item
|
||||
$item->restore();
|
||||
|
||||
// Return response
|
||||
return response('Done!', 204);
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\General;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\PricingCollection;
|
||||
use App\Services\StripeService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
class PricingController extends Controller
|
||||
{
|
||||
/**
|
||||
* PlanController constructor.
|
||||
*/
|
||||
public function __construct(StripeService $stripe)
|
||||
{
|
||||
$this->stripe = $stripe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all active plans
|
||||
*
|
||||
* @return PricingCollection
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
if (Cache::has('pricing')) {
|
||||
|
||||
// Get pricing from cache
|
||||
$pricing = Cache::get('pricing');
|
||||
} else {
|
||||
|
||||
// Store pricing to cache
|
||||
$pricing = Cache::rememberForever('pricing', function () {
|
||||
return $this->stripe->getActivePlans();
|
||||
});
|
||||
}
|
||||
|
||||
// Format pricing to collection
|
||||
$collection = new PricingCollection($pricing);
|
||||
|
||||
// Sort and return pricing
|
||||
return $collection->sortBy('product.metadata.capacity')
|
||||
->values()
|
||||
->all();
|
||||
}
|
||||
}
|
||||
@@ -1,578 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\General;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\SetupWizard\CreateAdminRequest;
|
||||
use App\Http\Requests\SetupWizard\StoreAppSetupRequest;
|
||||
use App\Http\Requests\SetupWizard\StoreDatabaseCredentialsRequest;
|
||||
use App\Http\Requests\SetupWizard\StoreEnvironmentSetupRequest;
|
||||
use App\Http\Requests\SetupWizard\StoreStripeBillingRequest;
|
||||
use App\Http\Requests\SetupWizard\StoreStripeCredentialsRequest;
|
||||
use App\Http\Requests\SetupWizard\StoreStripePlansRequest;
|
||||
use App\Page;
|
||||
use App\Services\StripeService;
|
||||
use App\Setting;
|
||||
use App\User;
|
||||
use App\UserSettings;
|
||||
use Artisan;
|
||||
use Cartalyst\Stripe\Exception\UnauthorizedException;
|
||||
use Doctrine\DBAL\Driver\PDOException;
|
||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\Str;
|
||||
use Schema;
|
||||
use Stripe;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
|
||||
class SetupWizardController extends Controller
|
||||
{
|
||||
/**
|
||||
* Inject Stripe Service
|
||||
*/
|
||||
public function __construct(StripeService $stripe)
|
||||
{
|
||||
$this->stripe = $stripe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify Envato purchase code
|
||||
*
|
||||
* @param Request $request
|
||||
* @return ResponseFactory|\Illuminate\Http\Response|mixed
|
||||
*/
|
||||
public function verify_purchase_code(Request $request)
|
||||
{
|
||||
// Check setup status
|
||||
if ($this->get_setup_status()) abort(410, 'Gone');
|
||||
|
||||
// Verify purchase code
|
||||
$response = Http::get('https://verify.vuefilemanager.com/api/verify-code/' . $request->purchaseCode);
|
||||
|
||||
if ($response->successful()) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
return response('Purchase code is invalid.', 400);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up database credentials
|
||||
*
|
||||
* @param StoreDatabaseCredentialsRequest $request
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function setup_database(StoreDatabaseCredentialsRequest $request)
|
||||
{
|
||||
// Check setup status
|
||||
if ($this->get_setup_status()) abort(410, 'Gone');
|
||||
|
||||
try {
|
||||
// Set temporary database connection
|
||||
config(['database.connections.test.driver' => $request->connection]);
|
||||
config(['database.connections.test.host' => $request->host]);
|
||||
config(['database.connections.test.port' => $request->port]);
|
||||
config(['database.connections.test.database' => $request->name]);
|
||||
config(['database.connections.test.username' => $request->username]);
|
||||
config(['database.connections.test.password' => $request->password]);
|
||||
|
||||
// Test connection
|
||||
\DB::connection('test')->getPdo();
|
||||
|
||||
} catch (PDOException $e) {
|
||||
throw new HttpException(500, $e->getMessage());
|
||||
}
|
||||
|
||||
setEnvironmentValue([
|
||||
'DB_CONNECTION' => $request->connection,
|
||||
'DB_HOST' => $request->host,
|
||||
'DB_PORT' => $request->port,
|
||||
'DB_DATABASE' => $request->name,
|
||||
'DB_USERNAME' => $request->username,
|
||||
'DB_PASSWORD' => $request->password,
|
||||
]);
|
||||
|
||||
// Clear cache
|
||||
Artisan::call('config:cache');
|
||||
|
||||
// Set up application
|
||||
$this->set_up_application();
|
||||
|
||||
// Store setup wizard progress
|
||||
Setting::create([
|
||||
'name' => 'setup_wizard_database',
|
||||
'value' => 1,
|
||||
]);
|
||||
|
||||
return response('Done', 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store and test stripe credentials
|
||||
*
|
||||
* @param StoreStripeCredentialsRequest $request
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function store_stripe_credentials(StoreStripeCredentialsRequest $request)
|
||||
{
|
||||
// Check setup status
|
||||
if ($this->get_setup_status()) abort(410, 'Gone');
|
||||
|
||||
// Create stripe instance
|
||||
$stripe = Stripe::make($request->secret, '2020-03-02');
|
||||
|
||||
// Try to get stripe account details
|
||||
try {
|
||||
$stripe->account()->details();
|
||||
} catch (UnauthorizedException $e) {
|
||||
throw new HttpException(401, $e->getMessage());
|
||||
}
|
||||
|
||||
// Get options
|
||||
$settings = collect([
|
||||
[
|
||||
'name' => 'stripe_currency',
|
||||
'value' => $request->currency,
|
||||
],
|
||||
[
|
||||
'name' => 'payments_configured',
|
||||
'value' => 1,
|
||||
],
|
||||
[
|
||||
'name' => 'payments_active',
|
||||
'value' => 1,
|
||||
],
|
||||
]);
|
||||
|
||||
// Store options
|
||||
$settings->each(function ($col) {
|
||||
Setting::updateOrCreate(['name' => $col['name']], $col);
|
||||
});
|
||||
|
||||
// Set stripe credentials to .env
|
||||
setEnvironmentValue([
|
||||
'CASHIER_CURRENCY' => $request->currency,
|
||||
'STRIPE_KEY' => $request->key,
|
||||
'STRIPE_SECRET' => $request->secret,
|
||||
'STRIPE_WEBHOOK_SECRET' => $request->webhookSecret,
|
||||
]);
|
||||
|
||||
// Clear cache
|
||||
Artisan::call('config:cache');
|
||||
|
||||
return response('Done', 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store Stripe billings
|
||||
*
|
||||
* @param StoreStripeBillingRequest $request
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function store_stripe_billings(StoreStripeBillingRequest $request)
|
||||
{
|
||||
// Check setup status
|
||||
if ($this->get_setup_status()) abort(410, 'Gone');
|
||||
|
||||
// Get options
|
||||
$settings = collect([
|
||||
[
|
||||
'name' => 'billing_phone_number',
|
||||
'value' => $request->billing_phone_number,
|
||||
],
|
||||
[
|
||||
'name' => 'billing_postal_code',
|
||||
'value' => $request->billing_postal_code,
|
||||
],
|
||||
[
|
||||
'name' => 'billing_vat_number',
|
||||
'value' => $request->billing_vat_number,
|
||||
],
|
||||
[
|
||||
'name' => 'billing_address',
|
||||
'value' => $request->billing_address,
|
||||
],
|
||||
[
|
||||
'name' => 'billing_country',
|
||||
'value' => $request->billing_country,
|
||||
],
|
||||
[
|
||||
'name' => 'billing_state',
|
||||
'value' => $request->billing_state,
|
||||
],
|
||||
[
|
||||
'name' => 'billing_city',
|
||||
'value' => $request->billing_city,
|
||||
],
|
||||
[
|
||||
'name' => 'billing_name',
|
||||
'value' => $request->billing_name,
|
||||
],
|
||||
]);
|
||||
|
||||
// Store options
|
||||
$settings->each(function ($col) {
|
||||
Setting::updateOrCreate(['name' => $col['name']], $col);
|
||||
});
|
||||
|
||||
// Clear cache
|
||||
Artisan::call('config:cache');
|
||||
|
||||
return response('Done', 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Stripe subscription plan
|
||||
*
|
||||
* @param StoreStripePlansRequest $request
|
||||
*/
|
||||
public function store_stripe_plans(StoreStripePlansRequest $request)
|
||||
{
|
||||
// Check setup status
|
||||
if ($this->get_setup_status()) abort(410, 'Gone');
|
||||
|
||||
foreach ($request->input('plans') as $plan) {
|
||||
$this->stripe->createPlan($plan);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store environment setup
|
||||
*
|
||||
* @param StoreEnvironmentSetupRequest $request
|
||||
* @return string
|
||||
*/
|
||||
public function store_environment_setup(StoreEnvironmentSetupRequest $request)
|
||||
{
|
||||
// Check setup status
|
||||
if ($this->get_setup_status()) abort(410, 'Gone');
|
||||
|
||||
$storage_driver = $request->input('storage.driver');
|
||||
|
||||
if ($storage_driver === 'local') {
|
||||
|
||||
setEnvironmentValue([
|
||||
'FILESYSTEM_DRIVER' => 'local',
|
||||
]);
|
||||
}
|
||||
|
||||
if ($storage_driver === 's3') {
|
||||
|
||||
setEnvironmentValue([
|
||||
'FILESYSTEM_DRIVER' => $request->input('storage.driver'),
|
||||
'AWS_ACCESS_KEY_ID' => $request->input('storage.key'),
|
||||
'AWS_SECRET_ACCESS_KEY' => $request->input('storage.secret'),
|
||||
'AWS_DEFAULT_REGION' => $request->input('storage.region'),
|
||||
'AWS_BUCKET' => $request->input('storage.bucket'),
|
||||
]);
|
||||
}
|
||||
|
||||
if ($storage_driver === 'spaces') {
|
||||
|
||||
setEnvironmentValue([
|
||||
'FILESYSTEM_DRIVER' => $request->input('storage.driver'),
|
||||
'DO_SPACES_KEY' => $request->input('storage.key'),
|
||||
'DO_SPACES_SECRET' => $request->input('storage.secret'),
|
||||
'DO_SPACES_ENDPOINT' => $request->input('storage.endpoint'),
|
||||
'DO_SPACES_REGION' => $request->input('storage.region'),
|
||||
'DO_SPACES_BUCKET' => $request->input('storage.bucket'),
|
||||
]);
|
||||
}
|
||||
|
||||
if ($storage_driver === 'wasabi') {
|
||||
|
||||
setEnvironmentValue([
|
||||
'FILESYSTEM_DRIVER' => $request->input('storage.driver'),
|
||||
'WASABI_KEY' => $request->input('storage.key'),
|
||||
'WASABI_SECRET' => $request->input('storage.secret'),
|
||||
'WASABI_ENDPOINT' => $request->input('storage.endpoint'),
|
||||
'WASABI_REGION' => $request->input('storage.region'),
|
||||
'WASABI_BUCKET' => $request->input('storage.bucket'),
|
||||
]);
|
||||
}
|
||||
|
||||
if ($storage_driver === 'backblaze') {
|
||||
|
||||
setEnvironmentValue([
|
||||
'FILESYSTEM_DRIVER' => $request->input('storage.driver'),
|
||||
'BACKBLAZE_KEY' => $request->input('storage.key'),
|
||||
'BACKBLAZE_SECRET' => $request->input('storage.secret'),
|
||||
'BACKBLAZE_ENDPOINT' => $request->input('storage.endpoint'),
|
||||
'BACKBLAZE_REGION' => $request->input('storage.region'),
|
||||
'BACKBLAZE_BUCKET' => $request->input('storage.bucket'),
|
||||
]);
|
||||
}
|
||||
|
||||
setEnvironmentValue([
|
||||
'MAIL_DRIVER' => $request->input('mail.driver'),
|
||||
'MAIL_HOST' => $request->input('mail.host'),
|
||||
'MAIL_PORT' => $request->input('mail.port'),
|
||||
'MAIL_USERNAME' => $request->input('mail.username'),
|
||||
'MAIL_PASSWORD' => $request->input('mail.password'),
|
||||
'MAIL_ENCRYPTION' => $request->input('mail.encryption'),
|
||||
]);
|
||||
|
||||
// Clear cache
|
||||
Artisan::call('config:cache');
|
||||
|
||||
return response('Done', 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store app settings
|
||||
* @param StoreAppSetupRequest $request
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function store_app_settings(StoreAppSetupRequest $request)
|
||||
{
|
||||
// Check setup status
|
||||
if ($this->get_setup_status()) abort(410, 'Gone');
|
||||
|
||||
// Store Logo
|
||||
if ($request->hasFile('logo')) {
|
||||
$logo = store_system_image($request->file('logo'), 'system');
|
||||
}
|
||||
|
||||
// Store Logo horizontal
|
||||
if ($request->hasFile('logo_horizontal')) {
|
||||
$logo_horizontal = store_system_image($request->file('logo_horizontal'), 'system');
|
||||
}
|
||||
|
||||
// Store favicon
|
||||
if ($request->hasFile('favicon')) {
|
||||
$favicon = store_system_image($request->file('favicon'), 'system');
|
||||
}
|
||||
|
||||
// Get options
|
||||
$settings = collect([
|
||||
[
|
||||
'name' => 'app_title',
|
||||
'value' => $request->title,
|
||||
],
|
||||
[
|
||||
'name' => 'app_description',
|
||||
'value' => $request->description,
|
||||
],
|
||||
[
|
||||
'name' => 'app_logo',
|
||||
'value' => $request->hasFile('logo') ? $logo : null,
|
||||
],
|
||||
[
|
||||
'name' => 'app_logo_horizontal',
|
||||
'value' => $request->hasFile('logo_horizontal') ? $logo_horizontal : null,
|
||||
],
|
||||
[
|
||||
'name' => 'app_favicon',
|
||||
'value' => $request->hasFile('favicon') ? $favicon : null,
|
||||
],
|
||||
[
|
||||
'name' => 'google_analytics',
|
||||
'value' => $request->googleAnalytics,
|
||||
],
|
||||
[
|
||||
'name' => 'contact_email',
|
||||
'value' => $request->contactMail,
|
||||
],
|
||||
[
|
||||
'name' => 'registration',
|
||||
'value' => $request->userRegistration,
|
||||
],
|
||||
[
|
||||
'name' => 'storage_limitation',
|
||||
'value' => $request->storageLimitation,
|
||||
],
|
||||
[
|
||||
'name' => 'storage_default',
|
||||
'value' => $request->defaultStorage ? $request->defaultStorage : 5,
|
||||
],
|
||||
]);
|
||||
|
||||
// Store options
|
||||
$settings->each(function ($col) {
|
||||
Setting::updateOrCreate(['name' => $col['name']], $col);
|
||||
});
|
||||
|
||||
setEnvironmentValue([
|
||||
'APP_NAME' => Str::camel($request->title),
|
||||
]);
|
||||
|
||||
return response('Done', 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and login admin account
|
||||
*
|
||||
* @param Request $request
|
||||
* @return ResponseFactory|\Illuminate\Http\Response|\Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function create_admin_account(Request $request)
|
||||
{
|
||||
// Check setup status
|
||||
if ($this->get_setup_status()) abort(410, 'Gone');
|
||||
|
||||
// Validate request
|
||||
$request->validate([
|
||||
'email' => 'required|string|email|unique:users',
|
||||
'password' => 'required|string|min:6|confirmed',
|
||||
'name' => 'required|string',
|
||||
'purchase_code' => 'required|string',
|
||||
'license' => 'required|string',
|
||||
'avatar' => 'sometimes|file',
|
||||
]);
|
||||
|
||||
// Store avatar
|
||||
if ($request->hasFile('avatar')) {
|
||||
$avatar = store_avatar($request->file('avatar'), 'avatars');
|
||||
}
|
||||
|
||||
// Create user
|
||||
$user = User::forceCreate([
|
||||
'avatar' => $request->hasFile('avatar') ? $avatar : null,
|
||||
'name' => $request->name,
|
||||
'role' => 'admin',
|
||||
'email' => $request->email,
|
||||
'password' => Hash::make($request->password),
|
||||
]);
|
||||
|
||||
// Get default storage capacity
|
||||
$storage_capacity = Setting::where('name', 'storage_default')->first();
|
||||
|
||||
// Create settings
|
||||
UserSettings::forceCreate([
|
||||
'user_id' => $user->id,
|
||||
'storage_capacity' => $storage_capacity->value,
|
||||
]);
|
||||
|
||||
// Store setup wizard progress
|
||||
Setting::updateOrCreate([
|
||||
'name' => 'setup_wizard_success',
|
||||
'value' => 1,
|
||||
]);
|
||||
|
||||
// Store License
|
||||
Setting::updateOrCreate([
|
||||
'name' => 'license',
|
||||
'value' => $request->license,
|
||||
]);
|
||||
|
||||
// Store Purchase Code
|
||||
Setting::updateOrCreate([
|
||||
'name' => 'purchase_code',
|
||||
'value' => $request->purchase_code,
|
||||
]);
|
||||
|
||||
// Create legal pages and index content
|
||||
if ($request->license === 'Extended') {
|
||||
|
||||
$pages = collect(config('content.pages'));
|
||||
$content = collect(config('content.content'));
|
||||
|
||||
$content->each(function ($content) {
|
||||
Setting::updateOrCreate($content);
|
||||
});
|
||||
|
||||
$pages->each(function ($page) {
|
||||
Page::updateOrCreate($page);
|
||||
});
|
||||
}
|
||||
|
||||
// Retrieve access token
|
||||
$response = Route::dispatch(self::make_login_request($request));
|
||||
|
||||
// Send access token to user if request is successful
|
||||
if ($response->isSuccessful()) {
|
||||
|
||||
$data = json_decode($response->content(), true);
|
||||
|
||||
return response('Admin was created', 200)->cookie('access_token', $data['access_token'], 43200);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrate database and generate necessary things
|
||||
*/
|
||||
private function set_up_application()
|
||||
{
|
||||
// Generate app key
|
||||
Artisan::call('key:generate', [
|
||||
'--force' => true
|
||||
]);
|
||||
|
||||
// Migrate database
|
||||
Artisan::call('migrate:fresh', [
|
||||
'--force' => true
|
||||
]);
|
||||
|
||||
// Create Passport Keys
|
||||
Artisan::call('passport:keys', [
|
||||
'--force' => true
|
||||
]);
|
||||
|
||||
// Create Password grant client
|
||||
Artisan::call('passport:client', [
|
||||
'--password' => true,
|
||||
'--name' => 'vuefilemanager',
|
||||
]);
|
||||
|
||||
// Create Personal access client
|
||||
Artisan::call('passport:client', [
|
||||
'--personal' => true,
|
||||
'--name' => 'shared',
|
||||
]);
|
||||
|
||||
// Get generated client
|
||||
$client = \DB::table('oauth_clients')->where('name', '=', 'vuefilemanager')->first();
|
||||
|
||||
// Set passport client to .env
|
||||
setEnvironmentValue([
|
||||
'PASSPORT_CLIENT_ID' => $client->id,
|
||||
'PASSPORT_CLIENT_SECRET' => $client->secret,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make login request for get access token
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Request
|
||||
*/
|
||||
private static function make_login_request($request)
|
||||
{
|
||||
$request->request->add([
|
||||
'grant_type' => 'password',
|
||||
'client_id' => config('services.passport.client_id'),
|
||||
'client_secret' => config('services.passport.client_secret'),
|
||||
'username' => $request->email,
|
||||
'password' => $request->password,
|
||||
'scope' => 'master',
|
||||
]);
|
||||
|
||||
return Request::create(url('/oauth/token'), 'POST', $request->all());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get setup wizard status
|
||||
*
|
||||
* @return |null
|
||||
*/
|
||||
private function get_setup_status()
|
||||
{
|
||||
try {
|
||||
// Check database connections
|
||||
DB::getPdo();
|
||||
|
||||
// Get setup_wizard status
|
||||
return Schema::hasTable('settings') ? Setting::where('name', 'setup_wizard_success')->first() : false;
|
||||
|
||||
} catch (PDOException $e) {
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\General;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Page;
|
||||
use App\Setting;
|
||||
use Artisan;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class UpgradeAppController extends Controller
|
||||
{
|
||||
/**
|
||||
* Upgrade account from 1.6 to 1.7
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function upgrade(Request $request)
|
||||
{
|
||||
$upgraded = Setting::where('name', 'latest_upgrade')->first();
|
||||
|
||||
if ($upgraded && $upgraded->value === '1.7') abort(401);
|
||||
|
||||
// Create legal pages and index content
|
||||
if ($request->license === 'Extended') {
|
||||
|
||||
$pages = collect(config('content.pages'));
|
||||
$content = collect(config('content.content'));
|
||||
|
||||
$content->each(function ($content) {
|
||||
Setting::updateOrCreate($content);
|
||||
});
|
||||
|
||||
$pages->each(function ($page) {
|
||||
Page::updateOrCreate($page);
|
||||
});
|
||||
}
|
||||
|
||||
// Store Logo
|
||||
if ($request->hasFile('logo')) {
|
||||
$logo = store_system_image($request->file('logo'), 'system');
|
||||
}
|
||||
|
||||
// Store Logo horizontal
|
||||
if ($request->hasFile('logo_horizontal')) {
|
||||
$logo_horizontal = store_system_image($request->file('logo_horizontal'), 'system');
|
||||
}
|
||||
|
||||
// Store favicon
|
||||
if ($request->hasFile('favicon')) {
|
||||
$favicon = store_system_image($request->file('favicon'), 'system');
|
||||
}
|
||||
|
||||
// Get options
|
||||
$settings = collect([
|
||||
[
|
||||
'name' => 'setup_wizard_database',
|
||||
'value' => 1,
|
||||
],
|
||||
[
|
||||
'name' => 'setup_wizard_success',
|
||||
'value' => 1,
|
||||
],
|
||||
[
|
||||
'name' => 'license',
|
||||
'value' => $request->license,
|
||||
],
|
||||
[
|
||||
'name' => 'purchase_code',
|
||||
'value' => $request->purchase_code,
|
||||
],
|
||||
[
|
||||
'name' => 'app_title',
|
||||
'value' => $request->title,
|
||||
],
|
||||
[
|
||||
'name' => 'app_description',
|
||||
'value' => $request->description,
|
||||
],
|
||||
[
|
||||
'name' => 'app_logo',
|
||||
'value' => $request->hasFile('logo') ? $logo : null,
|
||||
],
|
||||
[
|
||||
'name' => 'app_logo_horizontal',
|
||||
'value' => $request->hasFile('logo_horizontal') ? $logo_horizontal : null,
|
||||
],
|
||||
[
|
||||
'name' => 'app_favicon',
|
||||
'value' => $request->hasFile('favicon') ? $favicon : null,
|
||||
],
|
||||
[
|
||||
'name' => 'google_analytics',
|
||||
'value' => $request->googleAnalytics,
|
||||
],
|
||||
[
|
||||
'name' => 'contact_email',
|
||||
'value' => $request->contactMail,
|
||||
],
|
||||
[
|
||||
'name' => 'registration',
|
||||
'value' => $request->userRegistration,
|
||||
],
|
||||
[
|
||||
'name' => 'storage_limitation',
|
||||
'value' => $request->storageLimitation,
|
||||
],
|
||||
[
|
||||
'name' => 'storage_default',
|
||||
'value' => $request->defaultStorage ? $request->defaultStorage : 5,
|
||||
],
|
||||
[
|
||||
'name' => 'latest_upgrade',
|
||||
'value' => '1.7',
|
||||
],
|
||||
]);
|
||||
|
||||
// Store options
|
||||
$settings->each(function ($col) {
|
||||
Setting::updateOrCreate(['name' => $col['name']], $col);
|
||||
});
|
||||
|
||||
return response('Done', 200);
|
||||
}
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Tools\Demo;
|
||||
use App\Setting;
|
||||
use Artisan;
|
||||
use Stripe;
|
||||
use Cartalyst\Stripe\Exception\UnauthorizedException;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
|
||||
class SettingController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get table content
|
||||
*
|
||||
* @param Request $request
|
||||
* @return mixed
|
||||
*/
|
||||
public function show(Request $request)
|
||||
{
|
||||
$column = $request->get('column');
|
||||
|
||||
if (strpos($column, '|') !== false) {
|
||||
|
||||
$columns = explode('|', $column);
|
||||
|
||||
return Setting::whereIn('name', $columns)->pluck('value', 'name');
|
||||
}
|
||||
|
||||
return Setting::where('name', $column)->pluck('value', 'name');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(Request $request)
|
||||
{
|
||||
// Check if is demo
|
||||
if (env('APP_DEMO')) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Store image if exist
|
||||
if ($request->hasFile($request->name)) {
|
||||
|
||||
// Store image
|
||||
$image_path = store_system_image($request->file($request->name), 'system');
|
||||
|
||||
// Find and update image path
|
||||
Setting::updateOrCreate(['name' => $request->name], [
|
||||
'value' => $image_path
|
||||
]);
|
||||
|
||||
return response('Done', 204);
|
||||
}
|
||||
|
||||
// Find and update variable
|
||||
Setting::updateOrCreate(['name' => $request->name], [
|
||||
'value' => $request->value
|
||||
]);
|
||||
|
||||
return response('Done', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set new email credentials to .env file
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function set_email(Request $request)
|
||||
{
|
||||
// Check if is demo
|
||||
if (env('APP_DEMO')) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
setEnvironmentValue([
|
||||
'MAIL_DRIVER' => $request->input('driver'),
|
||||
'MAIL_HOST' => $request->input('host'),
|
||||
'MAIL_PORT' => $request->input('port'),
|
||||
'MAIL_USERNAME' => $request->input('username'),
|
||||
'MAIL_PASSWORD' => $request->input('password'),
|
||||
'MAIL_ENCRYPTION' => $request->input('encryption'),
|
||||
]);
|
||||
|
||||
// Clear config cache
|
||||
Artisan::call('config:clear');
|
||||
Artisan::call('config:cache');
|
||||
|
||||
return response('Done', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure stripe additionally
|
||||
*
|
||||
* @param Request $request
|
||||
*/
|
||||
public function set_stripe(Request $request)
|
||||
{
|
||||
// Get stripe status
|
||||
$is_stripe = get_setting('payments_configured');
|
||||
|
||||
// Check setup status
|
||||
if ($is_stripe) abort(401, 'Gone');
|
||||
|
||||
// Create stripe instance
|
||||
$stripe = Stripe::make($request->secret, '2020-03-02');
|
||||
|
||||
// Try to get stripe account details
|
||||
try {
|
||||
$stripe->account()->details();
|
||||
} catch (UnauthorizedException $e) {
|
||||
throw new HttpException(401, $e->getMessage());
|
||||
}
|
||||
|
||||
// Get options
|
||||
$settings = collect([
|
||||
[
|
||||
'name' => 'stripe_currency',
|
||||
'value' => $request->currency,
|
||||
],
|
||||
[
|
||||
'name' => 'payments_configured',
|
||||
'value' => 1,
|
||||
],
|
||||
[
|
||||
'name' => 'payments_active',
|
||||
'value' => 1,
|
||||
],
|
||||
]);
|
||||
|
||||
// Store options
|
||||
$settings->each(function ($col) {
|
||||
Setting::updateOrCreate(['name' => $col['name']], $col);
|
||||
});
|
||||
|
||||
// Set stripe credentials to .env
|
||||
setEnvironmentValue([
|
||||
'CASHIER_CURRENCY' => $request->currency,
|
||||
'STRIPE_KEY' => $request->key,
|
||||
'STRIPE_SECRET' => $request->secret,
|
||||
'STRIPE_WEBHOOK_SECRET' => $request->webhookSecret,
|
||||
]);
|
||||
|
||||
// Clear cache
|
||||
Artisan::call('cache:clear');
|
||||
Artisan::call('config:clear');
|
||||
Artisan::call('config:cache');
|
||||
}
|
||||
}
|
||||
@@ -1,409 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Sharing;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Share\AuthenticateShareRequest;
|
||||
use App\Http\Resources\ShareResource;
|
||||
use App\Http\Tools\Guardian;
|
||||
use App\Setting;
|
||||
use http\Env\Response;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Support\Facades\Cookie;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Arr;
|
||||
use App\FileManagerFolder;
|
||||
use App\FileManagerFile;
|
||||
use App\User;
|
||||
use App\Share;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class FileSharingController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Show page index and delete access_token & shared_token cookie
|
||||
*
|
||||
* @return Factory|\Illuminate\View\View
|
||||
*/
|
||||
public function index($token)
|
||||
{
|
||||
// Get shared token
|
||||
$shared = get_shared($token);
|
||||
|
||||
if (! $shared) {
|
||||
return view("index");
|
||||
}
|
||||
|
||||
// Delete old access_token if exist
|
||||
Cookie::queue('shared_access_token', '', -1);
|
||||
|
||||
// Set cookies
|
||||
if ((int) $shared->protected) {
|
||||
|
||||
// Set shared token
|
||||
Cookie::queue('shared_token', $token, 43200);
|
||||
}
|
||||
|
||||
// Check if shared is image file and then show it
|
||||
if ($shared->type === 'file' && ! (int) $shared->protected) {
|
||||
|
||||
$image = FileManagerFile::where('user_id', $shared->user_id)
|
||||
->where('type', 'image')
|
||||
->where('unique_id', $shared->item_id)
|
||||
->first();
|
||||
|
||||
if ($image) {
|
||||
return $this->show_image($image);
|
||||
}
|
||||
}
|
||||
|
||||
// Get all settings
|
||||
$settings = Setting::all();
|
||||
|
||||
// Return page index
|
||||
return view("index")
|
||||
->with('settings', $settings ? json_decode($settings->pluck('value', 'name')->toJson()) : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image from storage and show it
|
||||
*
|
||||
* @param $file
|
||||
* @return \Symfony\Component\HttpFoundation\StreamedResponse
|
||||
*/
|
||||
private function show_image($file)
|
||||
{
|
||||
// Format pretty filename
|
||||
$file_pretty_name = $file->name . '.' . $file->mimetype;
|
||||
|
||||
// Get file path
|
||||
$path = '/file-manager/' . $file->basename;
|
||||
|
||||
// Check if file exist
|
||||
if (!Storage::exists($path)) abort(404);
|
||||
|
||||
$header = [
|
||||
"Content-Type" => Storage::mimeType($path),
|
||||
"Content-Length" => Storage::size($path),
|
||||
"Accept-Ranges" => "bytes",
|
||||
"Content-Range" => "bytes 0-600/" . Storage::size($path),
|
||||
];
|
||||
|
||||
// Get file
|
||||
return Storage::response($path, $file_pretty_name, $header);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Password for protected item
|
||||
*
|
||||
* @param AuthenticateShareRequest $request
|
||||
* @param $token
|
||||
* @return array
|
||||
*/
|
||||
public function authenticate(AuthenticateShareRequest $request, $token)
|
||||
{
|
||||
// Get sharing record
|
||||
$shared = Share::where(DB::raw('BINARY `token`'), $token)->firstOrFail();
|
||||
|
||||
// Check password
|
||||
if (!Hash::check($request->password, $shared->password)) {
|
||||
|
||||
abort(401, __('vuefilemanager.incorrect_password'));
|
||||
}
|
||||
|
||||
// Get owner of shared content
|
||||
$user = User::find($shared->user_id);
|
||||
|
||||
// Define scope
|
||||
$scope = !is_null($shared->permission) ? $shared->permission : 'visitor';
|
||||
|
||||
// Generate token for visitor/editor
|
||||
$access_token = $user->createToken('shared_access_token', [$scope])->accessToken;
|
||||
|
||||
// Return authorize token with shared options
|
||||
return response(new ShareResource($shared), 200)
|
||||
->cookie('shared_token', $shared->token, 43200)
|
||||
->cookie('shared_access_token', $access_token, 43200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Browse private folders
|
||||
*
|
||||
* @param Request $request
|
||||
* @param $unique_id
|
||||
* @return Collection
|
||||
*/
|
||||
public function get_private_folders(Request $request, $unique_id)
|
||||
{
|
||||
// Get sharing record
|
||||
$shared = Share::where('token', $request->cookie('shared_token'))->firstOrFail();
|
||||
|
||||
// Check if user can get directory
|
||||
Guardian::check_item_access($unique_id, $shared);
|
||||
|
||||
// Get files and folders
|
||||
list($folders, $files) = $this->get_items($unique_id, $shared);
|
||||
|
||||
// Collect folders and files to single array
|
||||
return collect([$folders, $files])->collapse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Browse public folders
|
||||
*
|
||||
* @param $unique_id
|
||||
* @return Collection
|
||||
*/
|
||||
public function get_public_folders($unique_id, $token)
|
||||
{
|
||||
// Get sharing record
|
||||
$shared = Share::where(DB::raw('BINARY `token`'), $token)->firstOrFail();
|
||||
|
||||
// Abort if folder is protected
|
||||
if ((int) $shared->protected) {
|
||||
abort(403, "Sorry, you don't have permission");
|
||||
}
|
||||
|
||||
// Check if user can get directory
|
||||
Guardian::check_item_access($unique_id, $shared);
|
||||
|
||||
// Get files and folders
|
||||
list($folders, $files) = $this->get_items($unique_id, $shared);
|
||||
|
||||
// Set thumbnail links for public files
|
||||
$files->map(function ($item) use ($token) {
|
||||
$item->setPublicUrl($token);
|
||||
});
|
||||
|
||||
// Collect folders and files to single array
|
||||
return collect([$folders, $files])->collapse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get shared public file record
|
||||
*
|
||||
* @param $token
|
||||
* @return mixed
|
||||
*/
|
||||
public function file_public($token)
|
||||
{
|
||||
// Get sharing record
|
||||
$shared = Share::where(DB::raw('BINARY `token`'), $token)->firstOrFail();
|
||||
|
||||
// Abort if file is protected
|
||||
if ((int) $shared->protected) {
|
||||
abort(403, "Sorry, you don't have permission");
|
||||
}
|
||||
|
||||
// Get file
|
||||
$file = FileManagerFile::where('user_id', $shared->user_id)
|
||||
->where('unique_id', $shared->item_id)
|
||||
->firstOrFail(['name', 'basename', 'thumbnail', 'type', 'filesize', 'mimetype']);
|
||||
|
||||
// Set urls
|
||||
$file->setPublicUrl($token);
|
||||
|
||||
// Return record
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get shared private file record
|
||||
*
|
||||
* @param $token
|
||||
* @return mixed
|
||||
*/
|
||||
public function file_private(Request $request)
|
||||
{
|
||||
// Get sharing record
|
||||
$shared = Share::where('token', $request->cookie('shared_token'))->firstOrFail();
|
||||
|
||||
// Return record
|
||||
return FileManagerFile::where('user_id', $shared->user_id)
|
||||
->where('unique_id', $shared->item_id)
|
||||
->firstOrFail(['name', 'basename', 'thumbnail', 'type', 'filesize', 'mimetype']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get navigation tree
|
||||
*
|
||||
* @param Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function get_private_navigation_tree(Request $request)
|
||||
{
|
||||
// Get sharing record
|
||||
$shared = get_shared($request->cookie('shared_token'));
|
||||
|
||||
// Check if user can get directory
|
||||
Guardian::check_item_access($shared->item_id, $shared);
|
||||
|
||||
// Get folders
|
||||
$folders = FileManagerFolder::with('folders:id,parent_id,unique_id,name')
|
||||
->where('parent_id', $shared->item_id)
|
||||
->where('user_id', $shared->user_id)
|
||||
->get(['id', 'parent_id', 'unique_id', 'name']);
|
||||
|
||||
// Return folder tree
|
||||
return [
|
||||
[
|
||||
'unique_id' => $shared->item_id,
|
||||
'name' => __('vuefilemanager.home'),
|
||||
'location' => 'public',
|
||||
'folders' => $folders,
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get navigation tree
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_public_navigation_tree($token)
|
||||
{
|
||||
// Get sharing record
|
||||
$shared = Share::where('token', $token)->firstOrFail();
|
||||
|
||||
// Check if user can get directory
|
||||
Guardian::check_item_access($shared->item_id, $shared);
|
||||
|
||||
// Get folders
|
||||
$folders = FileManagerFolder::with('folders:id,parent_id,unique_id,name')
|
||||
->where('parent_id', $shared->item_id)
|
||||
->where('user_id', $shared->user_id)
|
||||
->get(['id', 'parent_id', 'unique_id', 'name']);
|
||||
|
||||
// Return folder tree
|
||||
return [
|
||||
[
|
||||
'unique_id' => $shared->item_id,
|
||||
'name' => __('vuefilemanager.home'),
|
||||
'location' => 'public',
|
||||
'folders' => $folders,
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Search private files
|
||||
*
|
||||
* @param Request $request
|
||||
* @param $token
|
||||
* @return Collection
|
||||
*/
|
||||
public function search_private(Request $request)
|
||||
{
|
||||
// Get shared
|
||||
$shared = get_shared($request->cookie('shared_token'));
|
||||
|
||||
// Search files id db
|
||||
$searched_files = FileManagerFile::search($request->input('query'))
|
||||
->where('user_id', $shared->user_id)
|
||||
->get();
|
||||
$searched_folders = FileManagerFolder::search($request->input('query'))
|
||||
->where('user_id', $shared->user_id)
|
||||
->get();
|
||||
|
||||
// Get all children content
|
||||
$foldersIds = FileManagerFolder::with('folders:id,parent_id,unique_id,name')
|
||||
->where('user_id', $shared->user_id)
|
||||
->where('parent_id', $shared->item_id)
|
||||
->get();
|
||||
|
||||
// Get accessible folders
|
||||
$accessible_folder_ids = Arr::flatten([filter_folders_ids($foldersIds), $shared->item_id]);
|
||||
|
||||
// Filter files to only accessible files
|
||||
$files = $searched_files->filter(function ($file) use ($accessible_folder_ids) {
|
||||
return in_array($file->folder_id, $accessible_folder_ids);
|
||||
});
|
||||
|
||||
// Filter folders to only accessible folders
|
||||
$folders = $searched_folders->filter(function ($folder) use ($accessible_folder_ids) {
|
||||
return in_array($folder->unique_id, $accessible_folder_ids);
|
||||
});
|
||||
|
||||
// Collect folders and files to single array
|
||||
return collect([$folders, $files])->collapse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Search public files
|
||||
*
|
||||
* @param Request $request
|
||||
* @param $token
|
||||
* @return Collection
|
||||
*/
|
||||
public function search_public(Request $request, $token)
|
||||
{
|
||||
// Get shared
|
||||
$shared = get_shared($token);
|
||||
|
||||
// Abort if folder is protected
|
||||
if ((int) $shared->protected) {
|
||||
abort(403, "Sorry, you don't have permission");
|
||||
}
|
||||
|
||||
// Search files id db
|
||||
$searched_files = FileManagerFile::search($request->input('query'))
|
||||
->where('user_id', $shared->user_id)
|
||||
->get();
|
||||
$searched_folders = FileManagerFolder::search($request->input('query'))
|
||||
->where('user_id', $shared->user_id)
|
||||
->get();
|
||||
|
||||
// Get all children content
|
||||
$foldersIds = FileManagerFolder::with('folders:id,parent_id,unique_id,name')
|
||||
->where('user_id', $shared->user_id)
|
||||
->where('parent_id', $shared->item_id)
|
||||
->get();
|
||||
|
||||
// Get accessible folders
|
||||
$accessible_folder_ids = Arr::flatten([filter_folders_ids($foldersIds), $shared->item_id]);
|
||||
|
||||
// Filter files
|
||||
$files = $searched_files->filter(function ($file) use ($accessible_folder_ids, $token) {
|
||||
|
||||
// Set public urls
|
||||
$file->setPublicUrl($token);
|
||||
|
||||
// check if item is in accessible folders
|
||||
return in_array($file->folder_id, $accessible_folder_ids);
|
||||
});
|
||||
|
||||
// Filter folders
|
||||
$folders = $searched_folders->filter(function ($folder) use ($accessible_folder_ids) {
|
||||
|
||||
// check if item is in accessible folders
|
||||
return in_array($folder->unique_id, $accessible_folder_ids);
|
||||
});
|
||||
|
||||
// Collect folders and files to single array
|
||||
return collect([$folders, $files])->collapse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get folders and files
|
||||
*
|
||||
* @param $unique_id
|
||||
* @param $shared
|
||||
* @return array
|
||||
*/
|
||||
private function get_items($unique_id, $shared): array
|
||||
{
|
||||
$folders = FileManagerFolder::where('user_id', $shared->user_id)
|
||||
->where('parent_id', $unique_id)
|
||||
->get();
|
||||
|
||||
$files = FileManagerFile::where('user_id', $shared->user_id)
|
||||
->where('folder_id', $unique_id)
|
||||
->get();
|
||||
|
||||
return [$folders, $files];
|
||||
}
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\User;
|
||||
|
||||
use App\FileManagerFile;
|
||||
use App\FileManagerFolder;
|
||||
use App\Http\Resources\InvoiceCollection;
|
||||
use App\Http\Resources\StorageDetailResource;
|
||||
use App\Http\Resources\UserResource;
|
||||
use App\Http\Resources\UserStorageResource;
|
||||
use App\Http\Tools\Demo;
|
||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Http\Request;
|
||||
use ByteUnits\Metric;
|
||||
use App\User;
|
||||
|
||||
class AccountController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get all user data to frontend
|
||||
*
|
||||
* @return UserResource
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return new UserResource(
|
||||
Auth::user()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get storage details
|
||||
*
|
||||
* @return UserStorageResource
|
||||
*/
|
||||
public function storage()
|
||||
{
|
||||
return new UserStorageResource(
|
||||
Auth::user()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user invoices
|
||||
*
|
||||
* @return InvoiceCollection
|
||||
*/
|
||||
public function invoices() {
|
||||
return new InvoiceCollection(
|
||||
Auth::user()->invoices()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update user profile
|
||||
*
|
||||
* @param Request $request
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function update_profile(Request $request)
|
||||
{
|
||||
// Validate request
|
||||
$validator = Validator::make($request->all(), [
|
||||
'avatar' => 'file',
|
||||
'name' => 'string',
|
||||
'value' => 'string',
|
||||
]);
|
||||
|
||||
// Return error
|
||||
if ($validator->fails()) abort(400, 'Bad input');
|
||||
|
||||
// Get user
|
||||
$user = Auth::user();
|
||||
|
||||
// Check if is demo
|
||||
if (is_demo($user->id)) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Update data
|
||||
if ($request->hasFile('avatar')) {
|
||||
|
||||
// Update avatar
|
||||
$avatar = store_avatar($request->file('avatar'), 'avatars');
|
||||
|
||||
// Update data
|
||||
$user->update(['avatar' => $avatar]);
|
||||
|
||||
} else {
|
||||
|
||||
// Update text data
|
||||
$user->update(make_single_input($request));
|
||||
}
|
||||
|
||||
return response('Saved!', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update user settings relationship
|
||||
*
|
||||
* @param Request $request
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function update_user_settings(Request $request)
|
||||
{
|
||||
// TODO: validation
|
||||
// Get user
|
||||
$user = Auth::user();
|
||||
|
||||
// Check if is demo
|
||||
if (is_demo($user->id)) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Update text data
|
||||
$user->settings->update(make_single_input($request));
|
||||
|
||||
return response('Saved!', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change user password
|
||||
*
|
||||
* @param Request $request
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function change_password(Request $request)
|
||||
{
|
||||
// Validate request
|
||||
$request->validate([
|
||||
'password' => ['required', 'string', 'min:6', 'confirmed'],
|
||||
]);
|
||||
|
||||
// Get user
|
||||
$user = Auth::user();
|
||||
|
||||
if (is_demo($user->id)) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Change and store new password
|
||||
$user->password = Hash::make($request->input('password'));
|
||||
$user->save();
|
||||
|
||||
return response('Changed!', 204);
|
||||
}
|
||||
}
|
||||
@@ -1,172 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\User;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Payments\RegisterNewPaymentMethodRequest;
|
||||
use App\Http\Resources\PaymentCardCollection;
|
||||
use App\Http\Resources\PaymentCardResource;
|
||||
use App\Http\Resources\PaymentDefaultCardResource;
|
||||
use App\Http\Tools\Demo;
|
||||
use App\Services\StripeService;
|
||||
use Auth;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Laravel\Cashier\PaymentMethod;
|
||||
|
||||
class PaymentMethodsController extends Controller
|
||||
{
|
||||
/**
|
||||
* PaymentMethodsController constructor.
|
||||
*/
|
||||
public function __construct(StripeService $stripe)
|
||||
{
|
||||
$this->stripe = $stripe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user payment methods grouped by default and others
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
if (!$user->hasPaymentMethod()) {
|
||||
return abort(204, 'User don\'t have any payment methods');
|
||||
}
|
||||
|
||||
$slug_payment_methods = 'payment-methods-user-' . $user->id;
|
||||
$slug_default_payment_method = 'default-payment-methods-user-' . $user->id;
|
||||
|
||||
if (Cache::has($slug_payment_methods) && Cache::has($slug_default_payment_method)) {
|
||||
|
||||
$defaultPaymentMethod = Cache::get($slug_default_payment_method);
|
||||
$paymentMethodsMapped = Cache::get($slug_payment_methods);
|
||||
|
||||
} else {
|
||||
|
||||
// Get default payment method
|
||||
$defaultPaymentMethod = Cache::rememberForever($slug_default_payment_method, function () use ($user) {
|
||||
|
||||
$defaultPaymentMethodObject = $user->defaultPaymentMethod();
|
||||
|
||||
return $defaultPaymentMethodObject instanceof PaymentMethod
|
||||
? $defaultPaymentMethodObject->asStripePaymentMethod()
|
||||
: $defaultPaymentMethodObject;
|
||||
});
|
||||
|
||||
// filter payment methods without default payment
|
||||
$paymentMethodsMapped = Cache::rememberForever($slug_payment_methods, function () use ($defaultPaymentMethod, $user) {
|
||||
|
||||
$paymentMethods = $user->paymentMethods()->filter(function ($paymentMethod) use ($defaultPaymentMethod) {
|
||||
return $paymentMethod->id !== $defaultPaymentMethod->id;
|
||||
});
|
||||
|
||||
// Get payment methods
|
||||
return $paymentMethods->map(function ($paymentMethod) {
|
||||
return $paymentMethod->asStripePaymentMethod();
|
||||
})->values()->all();
|
||||
});
|
||||
}
|
||||
|
||||
if (!$user->card_brand || !$user->stripe_id || is_null($paymentMethodsMapped) && is_null($paymentMethodsMapped)) {
|
||||
return [
|
||||
'default' => null,
|
||||
'others' => [],
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'default' => $defaultPaymentMethod instanceof PaymentMethod
|
||||
? new PaymentCardResource($defaultPaymentMethod)
|
||||
: new PaymentDefaultCardResource($defaultPaymentMethod),
|
||||
'others' => new PaymentCardCollection($paymentMethodsMapped),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update default payment method
|
||||
*
|
||||
* @param Request $request
|
||||
* @param $id
|
||||
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function update($id)
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
// Check if is demo
|
||||
if (is_demo($user->id)) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Update DefaultPayment Method
|
||||
$user->updateDefaultPaymentMethod($id);
|
||||
|
||||
// Sync default payment method
|
||||
$user->updateDefaultPaymentMethodFromStripe();
|
||||
|
||||
// Clear cached payment methods
|
||||
cache_forget_many([
|
||||
'payment-methods-user-' . $user->id,
|
||||
'default-payment-methods-user-' . $user->id
|
||||
]);
|
||||
|
||||
return response('Done', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register new payment method for user
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function store(RegisterNewPaymentMethodRequest $request)
|
||||
{
|
||||
// Get user
|
||||
$user = Auth::user();
|
||||
|
||||
// Check if is demo
|
||||
if (is_demo($user->id)) {
|
||||
return response('Done', 201);
|
||||
}
|
||||
|
||||
// Register new payment method
|
||||
$this->stripe->registerNewPaymentMethod($request, $user);
|
||||
|
||||
return response('Done', 201);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete user payment method
|
||||
*
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
// Check if is demo
|
||||
if (is_demo($user->id)) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Get payment method
|
||||
$paymentMethod = $user->findPaymentMethod($id);
|
||||
|
||||
// Delete payment method
|
||||
$paymentMethod->delete();
|
||||
|
||||
// Sync default payment method
|
||||
$user->updateDefaultPaymentMethodFromStripe();
|
||||
|
||||
// Clear cached payment methods
|
||||
cache_forget_many([
|
||||
'payment-methods-user-' . $user->id,
|
||||
'default-payment-methods-user-' . $user->id
|
||||
]);
|
||||
|
||||
return response('Done!', 204);
|
||||
}
|
||||
}
|
||||
@@ -1,154 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\User;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Subscription\StoreUpgradeAccountRequest;
|
||||
use App\Http\Resources\UserSubscription;
|
||||
use App\Http\Tools\Demo;
|
||||
use App\Invoice;
|
||||
use App\Services\StripeService;
|
||||
use Auth;
|
||||
use Cartalyst\Stripe\Exception\CardErrorException;
|
||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Laravel\Cashier\Exceptions\IncompletePayment;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
|
||||
class SubscriptionController extends Controller
|
||||
{
|
||||
private $stripe;
|
||||
|
||||
/**
|
||||
* SubscriptionController constructor.
|
||||
* @param $payment
|
||||
*/
|
||||
public function __construct(StripeService $stripe)
|
||||
{
|
||||
$this->stripe = $stripe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate setup intent
|
||||
*
|
||||
* @return \Stripe\SetupIntent
|
||||
*/
|
||||
public function stripe_setup_intent()
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
return $this->stripe->getSetupIntent($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user subscription detail
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function show()
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
if (! $user->subscription('main')) {
|
||||
return abort(204, 'User don\'t have any subscription');
|
||||
}
|
||||
|
||||
$slug_user_subscription = 'subscription-user-' . $user->id;
|
||||
|
||||
if (Cache::has($slug_user_subscription)) {
|
||||
return Cache::get($slug_user_subscription);
|
||||
}
|
||||
|
||||
return Cache::rememberForever($slug_user_subscription, function () {
|
||||
return new UserSubscription(
|
||||
Auth::user()
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Upgrade account to subscription
|
||||
*
|
||||
* @param StoreUpgradeAccountRequest $request
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function upgrade(StoreUpgradeAccountRequest $request)
|
||||
{
|
||||
// Get user
|
||||
$user = Auth::user();
|
||||
|
||||
// Check if is demo
|
||||
if (is_demo($user->id)) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Forget user subscription
|
||||
Cache::forget('subscription-user-' . $user->id);
|
||||
|
||||
// Get requested plan
|
||||
$plan = $this->stripe->getPlan($request->input('plan.data.id'));
|
||||
|
||||
// Set user billing
|
||||
$user->setBilling($request->input('billing'));
|
||||
|
||||
// Update stripe customer billing info
|
||||
$this->stripe->updateCustomerDetails($user);
|
||||
|
||||
// Make subscription
|
||||
$this->stripe->createOrReplaceSubscription($request, $user);
|
||||
|
||||
// Update user storage limit
|
||||
$user->settings()->update([
|
||||
'storage_capacity' => $plan['product']['metadata']['capacity']
|
||||
]);
|
||||
|
||||
return response('Done!', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel Subscription
|
||||
*
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function cancel()
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
// Check if is demo
|
||||
if (is_demo($user->id)) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Cancel subscription
|
||||
$user->subscription('main')->cancel();
|
||||
|
||||
// Forget user subscription
|
||||
Cache::forget('subscription-user-' . $user->id);
|
||||
|
||||
return response('Done!', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resume Subscription
|
||||
*
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function resume()
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
// Check if is demo
|
||||
if (is_demo($user->id)) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Resume subscription
|
||||
$user->subscription('main')->resume();
|
||||
|
||||
// Forget user subscription
|
||||
Cache::forget('subscription-user-' . $user->id);
|
||||
|
||||
return response('Done!', 204);
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Services\StripeService;
|
||||
use App\Setting;
|
||||
use App\User;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use Laravel\Cashier\Http\Controllers\WebhookController as CashierController;
|
||||
|
||||
class WebhookController extends CashierController
|
||||
{
|
||||
public function __construct(StripeService $stripe)
|
||||
{
|
||||
$this->stripe = $stripe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a cancelled customer from a Stripe subscription.
|
||||
*
|
||||
* @param array $payload
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function handleCustomerSubscriptionDeleted($payload)
|
||||
{
|
||||
if ($user = $this->getUserByStripeId($payload['data']['object']['customer'])) {
|
||||
$user->subscriptions->filter(function ($subscription) use ($payload) {
|
||||
return $subscription->stripe_id === $payload['data']['object']['id'];
|
||||
})->each(function ($subscription) {
|
||||
$subscription->markAsCancelled();
|
||||
});
|
||||
}
|
||||
|
||||
// Get user
|
||||
$user = User::where('stripe_id', $payload['data']['object']['customer'])->firstOrFail();
|
||||
|
||||
// Get default storage capacity
|
||||
$default_storage = Setting::where('name', 'storage_default')->first();
|
||||
|
||||
// Update storage capacity
|
||||
$user->settings()->update(['storage_capacity' => $default_storage->value]);
|
||||
|
||||
return $this->successMethod();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Invoice Payment Succeeded
|
||||
*
|
||||
* @param $payload
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function handleInvoicePaymentSucceeded($payload)
|
||||
{
|
||||
// Get user
|
||||
$user = User::where('stripe_id', $payload['data']['object']['customer'])->firstOrFail();
|
||||
|
||||
// Get requested plan
|
||||
$plan = $this->stripe->getPlan($user->subscription('main')->stripe_plan);
|
||||
|
||||
// Update user storage limit
|
||||
$user->settings()->update([
|
||||
'storage_capacity' => $plan['product']['metadata']['capacity']
|
||||
]);
|
||||
|
||||
return $this->successMethod();
|
||||
}
|
||||
}
|
||||
@@ -1,531 +0,0 @@
|
||||
<?php
|
||||
|
||||
use App\FileManagerFile;
|
||||
use App\FileManagerFolder;
|
||||
use App\Setting;
|
||||
use App\Share;
|
||||
use ByteUnits\Metric;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Intervention\Image\ImageManagerStatic as Image;
|
||||
|
||||
/**
|
||||
* Obfuscate email
|
||||
*
|
||||
* @param $email
|
||||
* @return string
|
||||
*/
|
||||
function obfuscate_email($email)
|
||||
{
|
||||
$em = explode("@", $email);
|
||||
$name = implode('@', array_slice($em, 0, count($em) - 1));
|
||||
$len = floor(strlen($name) / 2);
|
||||
|
||||
return substr($name, 0, $len) . str_repeat('*', $len) . "@" . end($em);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get single value from settings table
|
||||
*
|
||||
* @param $setting
|
||||
* @return |null
|
||||
*/
|
||||
function get_setting($setting)
|
||||
{
|
||||
$row = Setting::where('name', $setting)->first();
|
||||
|
||||
return $row ? $row->value : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create paragraph from text
|
||||
*
|
||||
* @param $str
|
||||
* @return mixed|null|string|string[]
|
||||
*/
|
||||
function add_paragraphs($str)
|
||||
{
|
||||
// Trim whitespace
|
||||
if (($str = trim($str)) === '') return '';
|
||||
|
||||
// Standardize newlines
|
||||
$str = str_replace(array("\r\n", "\r"), "\n", $str);
|
||||
|
||||
// Trim whitespace on each line
|
||||
$str = preg_replace('~^[ \t]+~m', '', $str);
|
||||
$str = preg_replace('~[ \t]+$~m', '', $str);
|
||||
|
||||
// The following regexes only need to be executed if the string contains html
|
||||
if ($html_found = (strpos($str, '<') !== FALSE)) {
|
||||
// Elements that should not be surrounded by p tags
|
||||
$no_p = '(?:p|div|article|header|aside|hgroup|canvas|output|progress|section|figcaption|audio|video|nav|figure|footer|video|details|main|menu|summary|h[1-6r]|ul|ol|li|blockquote|d[dlt]|pre|t[dhr]|t(?:able|body|foot|head)|c(?:aption|olgroup)|form|s(?:elect|tyle)|a(?:ddress|rea)|ma(?:p|th))';
|
||||
|
||||
// Put at least two linebreaks before and after $no_p elements
|
||||
$str = preg_replace('~^<' . $no_p . '[^>]*+>~im', "\n$0", $str);
|
||||
$str = preg_replace('~</' . $no_p . '\s*+>$~im', "$0\n", $str);
|
||||
}
|
||||
|
||||
// Do the <p> magic!
|
||||
$str = '<p>' . trim($str) . '</p>';
|
||||
$str = preg_replace('~\n{2,}~', "</p>\n\n<p>", $str);
|
||||
|
||||
// The following regexes only need to be executed if the string contains html
|
||||
if ($html_found !== FALSE) {
|
||||
// Remove p tags around $no_p elements
|
||||
$str = preg_replace('~<p>(?=</?' . $no_p . '[^>]*+>)~i', '', $str);
|
||||
$str = preg_replace('~(</?' . $no_p . '[^>]*+>)</p>~i', '$1', $str);
|
||||
}
|
||||
|
||||
// Convert single linebreaks to <br />
|
||||
$str = preg_replace('~(?<!\n)\n(?!\n)~', "<br>\n", $str);
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set environment value
|
||||
*
|
||||
* @param $key
|
||||
* @param $value
|
||||
* @return bool
|
||||
*/
|
||||
function setEnvironmentValue(array $values)
|
||||
{
|
||||
$envFile = app()->environmentFilePath();
|
||||
$str = file_get_contents($envFile);
|
||||
|
||||
if (count($values) > 0) {
|
||||
foreach ($values as $envKey => $envValue) {
|
||||
|
||||
$str .= "\n"; // In case the searched variable is in the last line without \n
|
||||
$keyPosition = strpos($str, "{$envKey}=");
|
||||
$endOfLinePosition = strpos($str, "\n", $keyPosition);
|
||||
$oldLine = substr($str, $keyPosition, $endOfLinePosition - $keyPosition);
|
||||
|
||||
// If key does not exist, add it
|
||||
$str = str_replace($oldLine, "{$envKey}={$envValue}", $str);
|
||||
}
|
||||
}
|
||||
|
||||
$str = substr($str, 0, -1);
|
||||
if (!file_put_contents($envFile, $str)) return false;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get invoice number
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function get_invoice_number()
|
||||
{
|
||||
$invoices = \App\Invoice::all();
|
||||
|
||||
if ($invoices->isEmpty()) {
|
||||
return Carbon::now()->year . '001';
|
||||
} else {
|
||||
return (int)$invoices->last()->order + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Forget many cache keys at once
|
||||
* @param $cache
|
||||
*/
|
||||
function cache_forget_many($cache)
|
||||
{
|
||||
foreach ($cache as $item) {
|
||||
\Illuminate\Support\Facades\Cache::forget($item);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get app version from config
|
||||
*
|
||||
* @return \Illuminate\Config\Repository|mixed
|
||||
*/
|
||||
function get_storage()
|
||||
{
|
||||
return env('FILESYSTEM_DRIVER');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if is running AWS s3 as storage
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function is_storage_driver($driver)
|
||||
{
|
||||
if (is_array($driver)) {
|
||||
return in_array(config('filesystems.default'), $driver);
|
||||
}
|
||||
|
||||
return config('filesystems.default') === $driver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get app version from config
|
||||
*
|
||||
* @return \Illuminate\Config\Repository|mixed
|
||||
*/
|
||||
function get_version()
|
||||
{
|
||||
return config('vuefilemanager.version');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if is demo
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function is_demo($user_id)
|
||||
{
|
||||
return env('APP_DEMO', false) && $user_id === 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get folder or file item
|
||||
*
|
||||
* @param $type
|
||||
* @param $unique_id
|
||||
* @param $user_id
|
||||
* @return \Illuminate\Database\Eloquent\Builder|Model
|
||||
*/
|
||||
function get_item($type, $unique_id, $user_id)
|
||||
{
|
||||
|
||||
if ($type === 'folder') {
|
||||
|
||||
// Return folder item
|
||||
return FileManagerFolder::where('unique_id', $unique_id)
|
||||
->where('user_id', $user_id)
|
||||
->firstOrFail();
|
||||
}
|
||||
|
||||
// Return file item
|
||||
return FileManagerFile::where('unique_id', $unique_id)
|
||||
->where('user_id', $user_id)
|
||||
->firstOrFail();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get shared token
|
||||
*
|
||||
* @param $token
|
||||
* @return \Illuminate\Database\Eloquent\Builder|Model
|
||||
*/
|
||||
function get_shared($token)
|
||||
{
|
||||
|
||||
return Share::where(DB::raw('BINARY `token`'), $token)
|
||||
->firstOrFail();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if shared permission is editor
|
||||
*
|
||||
* @param $shared
|
||||
* @return bool
|
||||
*/
|
||||
function is_editor($shared)
|
||||
{
|
||||
|
||||
return $shared->permission === 'editor';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get unique id
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
function get_unique_id(): int
|
||||
{
|
||||
// Get files and folders
|
||||
$folders = FileManagerFolder::withTrashed()->get();
|
||||
$files = FileManagerFile::withTrashed()->get();
|
||||
|
||||
// Get last ids
|
||||
$folders_unique = $folders->isEmpty() ? 0 : $folders->last()->unique_id;
|
||||
$files_unique = $files->isEmpty() ? 0 : $files->last()->unique_id;
|
||||
|
||||
// Count new unique id
|
||||
$unique_id = $folders_unique > $files_unique ? $folders_unique + 1 : $files_unique + 1;
|
||||
|
||||
return $unique_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store user avatar to storage
|
||||
*
|
||||
* @param $image
|
||||
* @param $path
|
||||
* @return string
|
||||
*/
|
||||
function store_avatar($image, $path)
|
||||
{
|
||||
// Get directory
|
||||
$path = check_directory($path);
|
||||
|
||||
// Store avatar
|
||||
$image_path = Str::random(8) . '-' . $image->getClientOriginalName();
|
||||
|
||||
// Create intervention image
|
||||
$img = Image::make($image->getRealPath());
|
||||
|
||||
// Generate thumbnail
|
||||
$img->fit('150', '150')->stream();
|
||||
|
||||
// Store thumbnail to disk
|
||||
Storage::put($path . '/' . $image_path, $img);
|
||||
|
||||
// Return path to image
|
||||
return $path . '/' . $image_path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store system image
|
||||
*
|
||||
* @param $image
|
||||
* @param $path
|
||||
* @return string
|
||||
*/
|
||||
function store_system_image($image, $path)
|
||||
{
|
||||
// Get directory
|
||||
$path = check_directory($path);
|
||||
|
||||
// Store avatar
|
||||
$image_path = Str::random(8) . '-' . str_replace(' ', '', $image->getClientOriginalName());
|
||||
|
||||
// Store image to disk
|
||||
Storage::putFileAs($path, $image, $image_path);
|
||||
|
||||
// Return path to image
|
||||
return $path . '/' . $image_path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if directory exist, if no, then create it
|
||||
*
|
||||
* @param $directory
|
||||
* @return mixed
|
||||
*/
|
||||
function check_directory($directory)
|
||||
{
|
||||
if (!Storage::exists($directory)) {
|
||||
Storage::makeDirectory($directory);
|
||||
}
|
||||
|
||||
return $directory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make input from request
|
||||
*
|
||||
* @param $request
|
||||
* @return array
|
||||
*/
|
||||
function make_single_input($request)
|
||||
{
|
||||
// Create container
|
||||
$data = [];
|
||||
|
||||
// Add data to array
|
||||
$data[$request->name] = $request->value;
|
||||
|
||||
// Return input
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format integer to gigabytes
|
||||
*
|
||||
* @param $gigabytes
|
||||
* @return string
|
||||
*/
|
||||
function format_gigabytes($gigabytes)
|
||||
{
|
||||
if ($gigabytes >= 1000) {
|
||||
return Metric::gigabytes($gigabytes)->format('Tb/');
|
||||
} else {
|
||||
return Metric::gigabytes($gigabytes)->format('GB/');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert megabytes to bytes
|
||||
*
|
||||
* @param $megabytes
|
||||
* @return int|string
|
||||
*/
|
||||
function format_bytes($megabytes)
|
||||
{
|
||||
return Metric::megabytes($megabytes)->numberOfBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get storage usage in percent
|
||||
*
|
||||
* @param $used
|
||||
* @param $capacity
|
||||
* @return string
|
||||
*/
|
||||
function get_storage_fill_percentage($used, $capacity)
|
||||
{
|
||||
// Format gigabytes to bytes
|
||||
$total = intval(Metric::gigabytes($capacity)->numberOfBytes());
|
||||
|
||||
// Count progress
|
||||
$progress = ($used * 100) / $total;
|
||||
|
||||
// Return in 2 decimal
|
||||
return number_format((float)$progress, 2, '.', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user capacity fill by percentage
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function user_storage_percentage($id, $additionals = null)
|
||||
{
|
||||
$user = \App\User::findOrFail($id);
|
||||
|
||||
$used = $user->used_capacity;
|
||||
|
||||
if ($additionals) {
|
||||
$used = $user->used_capacity + $additionals;
|
||||
}
|
||||
|
||||
return get_storage_fill_percentage($used, $user->settings->storage_capacity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all key values in recursive array
|
||||
*
|
||||
* @param array $array
|
||||
* @param $needle
|
||||
* @return array
|
||||
*/
|
||||
function recursiveFind(array $array, $needle)
|
||||
{
|
||||
$iterator = new RecursiveArrayIterator($array);
|
||||
$recursive = new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::SELF_FIRST);
|
||||
$aHitList = array();
|
||||
foreach ($recursive as $key => $value) {
|
||||
if ($key === $needle) {
|
||||
array_push($aHitList, $value);
|
||||
}
|
||||
}
|
||||
return $aHitList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get values which appears only once in array
|
||||
* @param $arr
|
||||
* @return array
|
||||
*/
|
||||
function appeared_once($arr)
|
||||
{
|
||||
$array_count_values = array_count_values($arr);
|
||||
|
||||
$single_time_comming_values_array = [];
|
||||
|
||||
foreach ($array_count_values as $key => $val) {
|
||||
|
||||
if ($val == 1) {
|
||||
$single_time_comming_values_array[] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
return $single_time_comming_values_array;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $folders
|
||||
* @return array
|
||||
*/
|
||||
function filter_folders_ids($folders, $by_column = 'unique_id')
|
||||
{
|
||||
$folder_unique_ids = recursiveFind($folders->toArray(), $by_column);
|
||||
|
||||
return appeared_once($folder_unique_ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format localized date
|
||||
*
|
||||
* @param $date
|
||||
* @param string $format
|
||||
* @return string
|
||||
*/
|
||||
function format_date($date, $format = '%d. %B. %Y, %H:%M')
|
||||
{
|
||||
$start = Carbon::parse($date);
|
||||
|
||||
return $start->formatLocalized($format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file type from mimetype
|
||||
*
|
||||
* @param $file
|
||||
* @return string
|
||||
*/
|
||||
function get_file_type($file_mimetype)
|
||||
{
|
||||
// Get mimetype from file
|
||||
$mimetype = explode('/', $file_mimetype);
|
||||
|
||||
switch ($mimetype[0]) {
|
||||
case 'image':
|
||||
return 'image';
|
||||
break;
|
||||
case 'video':
|
||||
return 'video';
|
||||
break;
|
||||
case 'audio':
|
||||
return 'audio';
|
||||
break;
|
||||
default:
|
||||
return 'file';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get file type from mimetype
|
||||
*
|
||||
* @param $mimetype
|
||||
* @return mixed
|
||||
*/
|
||||
function get_file_type_from_mimetype($mimetype)
|
||||
{
|
||||
return explode('/', $mimetype)[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Format pretty name file
|
||||
*
|
||||
* @param $basename
|
||||
* @param $name
|
||||
* @param $mimetype
|
||||
* @return string
|
||||
*/
|
||||
function get_pretty_name($basename, $name, $mimetype)
|
||||
{
|
||||
$file_extension = substr(strrchr($basename, '.'), 1);
|
||||
|
||||
if (strpos($name, $file_extension) !== false) {
|
||||
return $name;
|
||||
}
|
||||
|
||||
if ($file_extension) {
|
||||
return $name . '.' . $file_extension;
|
||||
}
|
||||
|
||||
return $name . '.' . $mimetype;
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Check if current user subscribed plan is highest
|
||||
*
|
||||
* @param $id
|
||||
* @param $subscribed_capacity
|
||||
* @return int
|
||||
*/
|
||||
function is_highest_plan($plan)
|
||||
{
|
||||
$plans = app('rinvex.subscriptions.plan')->all();
|
||||
|
||||
$unsubscribed = $plans->filter(function ($item) use ($plan) {
|
||||
return $item->id !== $plan->id;
|
||||
});
|
||||
|
||||
$capacities = $unsubscribed->map(function ($item) {
|
||||
return $item->features->first()->value;
|
||||
});
|
||||
|
||||
return max(Arr::flatten($capacities)) < $plan->features->first()->value ? 1 : 0;
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http;
|
||||
|
||||
use App\Http\Middleware\AdminCheck;
|
||||
use App\Http\Middleware\CookieAuth;
|
||||
use App\Http\Middleware\LastCheck;
|
||||
use App\Http\Middleware\SharedAuth;
|
||||
use Illuminate\Foundation\Http\Kernel as HttpKernel;
|
||||
|
||||
class Kernel extends HttpKernel
|
||||
{
|
||||
/**
|
||||
* The application's global HTTP middleware stack.
|
||||
*
|
||||
* These middleware are run during every request to your application.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $middleware = [
|
||||
\App\Http\Middleware\TrustProxies::class,
|
||||
\App\Http\Middleware\CheckForMaintenanceMode::class,
|
||||
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
|
||||
\App\Http\Middleware\TrimStrings::class,
|
||||
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
|
||||
\Fruitcake\Cors\HandleCors::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* The application's route middleware groups.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $middlewareGroups = [
|
||||
'web' => [
|
||||
\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,
|
||||
],
|
||||
|
||||
'api' => [
|
||||
\App\Http\Middleware\EncryptCookies::class,
|
||||
//'throttle:60,1',
|
||||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* The application's route middleware.
|
||||
*
|
||||
* These middleware may be assigned to groups or used individually.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $routeMiddleware = [
|
||||
'auth.master' => CookieAuth::class,
|
||||
'auth.shared' => SharedAuth::class,
|
||||
'auth.admin' => AdminCheck::class,
|
||||
'auth' => \App\Http\Middleware\Authenticate::class,
|
||||
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
|
||||
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
|
||||
'can' => \Illuminate\Auth\Middleware\Authorize::class,
|
||||
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
|
||||
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
|
||||
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
|
||||
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
||||
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
|
||||
'scopes' => \Laravel\Passport\Http\Middleware\CheckScopes::class,
|
||||
'scope' => \Laravel\Passport\Http\Middleware\CheckForAnyScope::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* The priority-sorted list of middleware.
|
||||
*
|
||||
* This forces non-global middleware to always be in the given order.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $middlewarePriority = [
|
||||
\Illuminate\Session\Middleware\StartSession::class,
|
||||
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
|
||||
CookieAuth::class,
|
||||
SharedAuth::class,
|
||||
\App\Http\Middleware\Authenticate::class,
|
||||
\Illuminate\Routing\Middleware\ThrottleRequests::class,
|
||||
\Illuminate\Session\Middleware\AuthenticateSession::class,
|
||||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
\Illuminate\Auth\Middleware\Authorize::class,
|
||||
];
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class SendSupportForm extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
private $request;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($request)
|
||||
{
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the message.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
$from = config('mail.from')['address'];
|
||||
|
||||
return $this->from($from)
|
||||
->replyTo($this->request['email'])
|
||||
->subject('New Contact Message from ' . $this->request['email'])
|
||||
->view('mails.contact-message')
|
||||
->with('request', $this->request);
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class CookieAuth
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
if (!$request->bearerToken()) {
|
||||
if ($request->hasCookie('access_token')) {
|
||||
|
||||
$access_token = $request->cookie('access_token');
|
||||
|
||||
$request->headers->add(['Authorization' => 'Bearer ' . $access_token]);
|
||||
|
||||
}
|
||||
}
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use Closure;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class RedirectIfAuthenticated
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param string|null $guard
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next, $guard = null)
|
||||
{
|
||||
if (Auth::guard($guard)->check()) {
|
||||
return redirect(RouteServiceProvider::HOME);
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
|
||||
class SharedAuth
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
if (!$request->bearerToken()) {
|
||||
if ($request->hasCookie('shared_access_token')) {
|
||||
|
||||
$shared_access_token = $request->cookie('shared_access_token');
|
||||
|
||||
$request->headers->add(['Authorization' => 'Bearer ' . $shared_access_token]);
|
||||
|
||||
}
|
||||
}
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Fideloper\Proxy\TrustProxies as Middleware;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class TrustProxies extends Middleware
|
||||
{
|
||||
/**
|
||||
* The trusted proxies for this application.
|
||||
*
|
||||
* @var array|string
|
||||
*/
|
||||
protected $proxies;
|
||||
|
||||
/**
|
||||
* The headers that should be used to detect proxies.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $headers = Request::HEADER_X_FORWARDED_ALL;
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Laravel\Cashier\Payment;
|
||||
|
||||
class ConfirmPayment extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
/**
|
||||
* The PaymentIntent identifier.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $paymentId;
|
||||
|
||||
/**
|
||||
* The payment amount.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $amount;
|
||||
|
||||
/**
|
||||
* Create a new payment confirmation notification.
|
||||
*
|
||||
* @param \Laravel\Cashier\Payment $payment
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Payment $payment)
|
||||
{
|
||||
$this->paymentId = $payment->id;
|
||||
$this->amount = $payment->amount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification's delivery channels.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function via($notifiable)
|
||||
{
|
||||
return ['mail'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return \Illuminate\Notifications\Messages\MailMessage
|
||||
*/
|
||||
public function toMail($notifiable)
|
||||
{
|
||||
$url = route('cashier.payment', ['id' => $this->paymentId]);
|
||||
|
||||
return (new MailMessage)
|
||||
->subject(__('cashier.confirm_payment'))
|
||||
->greeting(__('cashier.confirm_amount', ['amount' => $this->amount]))
|
||||
->line(__('cashier.confirm_description'))
|
||||
->action(__('cashier.confirm_button'), $url);
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\SetupWizard;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class StoreStripeBillingRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'billing_phone_number' => 'sometimes|nullable|string',
|
||||
'billing_postal_code' => 'required|string',
|
||||
'billing_vat_number' => 'required|string',
|
||||
'billing_address' => 'required|string',
|
||||
'billing_country' => 'required|string',
|
||||
'billing_state' => 'required|string',
|
||||
'billing_city' => 'required|string',
|
||||
'billing_name' => 'required|string',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\SetupWizard;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class StoreStripeCredentialsRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'currency' => 'required|string',
|
||||
'webhookSecret' => 'required|string',
|
||||
'secret' => 'required|string',
|
||||
'key' => 'required|string',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\SetupWizard;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class StoreStripePlansRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'plans' => 'required|array',
|
||||
'plans.*.type' => 'required|string',
|
||||
'plans.*.attributes.name' => 'required|string',
|
||||
'plans.*.attributes.price' => 'required|string',
|
||||
'plans.*.attributes.description' => 'sometimes|nullable|string',
|
||||
'plans.*.attributes.capacity' => 'required|digits_between:1,9',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\Subscription;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class StoreUpgradeAccountRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
// Billings
|
||||
'billing' => 'required|array',
|
||||
'billing.billing_address' => 'required|string',
|
||||
'billing.billing_city' => 'required|string',
|
||||
'billing.billing_country' => 'required|string',
|
||||
'billing.billing_name' => 'required|string',
|
||||
'billing.billing_phone_number' => 'required|string',
|
||||
'billing.billing_postal_code' => 'required|string',
|
||||
'billing.billing_state' => 'required|string',
|
||||
|
||||
// Payment
|
||||
'payment' => 'required|array',
|
||||
'payment.type' => 'required|string',
|
||||
'payment.meta' => 'required|sometimes|array',
|
||||
'payment.meta.pm' => 'required|sometimes|string',
|
||||
|
||||
// Plan
|
||||
'plan.data' => 'required|array',
|
||||
'plan.data.attributes' => 'required|array',
|
||||
'plan.data.attributes.capacity' => 'required|digits_between:1,9',
|
||||
'plan.data.attributes.capacity_formatted' => 'required|string',
|
||||
'plan.data.attributes.currency' => 'required|string',
|
||||
'plan.data.attributes.description' => 'required|string',
|
||||
'plan.data.attributes.name' => 'required|string',
|
||||
'plan.data.attributes.price' => 'required|string',
|
||||
'plan.data.id' => 'required|string',
|
||||
'plan.data.type' => 'required|string',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
|
||||
class GatewayCollection extends ResourceCollection
|
||||
{
|
||||
public $collects = GatewayResource::class;
|
||||
|
||||
/**
|
||||
* Transform the resource collection into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => $this->collection,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class GatewayResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => [
|
||||
'id' => (string)$this->id,
|
||||
'type' => 'gateways',
|
||||
'attributes' => [
|
||||
'status' => $this->status,
|
||||
'sandbox' => $this->sandbox,
|
||||
'name' => $this->name,
|
||||
'slug' => $this->slug,
|
||||
'logo' => $this->logo,
|
||||
'client_id' => $this->client_id,
|
||||
'secret' => $this->secret,
|
||||
'webhook' => $this->webhook,
|
||||
'payment_processed' => $this->payment_processed,
|
||||
'optional' => $this->optional,
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
|
||||
class InvoiceAdminCollection extends ResourceCollection
|
||||
{
|
||||
public $collects = InvoiceAdminResource::class;
|
||||
|
||||
/**
|
||||
* Transform the resource collection into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => $this->collection,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use App\User;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use Laravel\Cashier\Cashier;
|
||||
|
||||
class InvoiceAdminResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
$user = User::where('stripe_id', $this['customer'])->first();
|
||||
|
||||
return [
|
||||
'data' => [
|
||||
'id' => $this['id'],
|
||||
'type' => 'invoices',
|
||||
'attributes' => [
|
||||
'customer' => $this['customer'],
|
||||
'total' => Cashier::formatAmount($this['total']),
|
||||
'currency' => $this['currency'],
|
||||
'created_at_formatted' => format_date($this['created']),
|
||||
'created_at' => $this['created'],
|
||||
'order' => $this['number'],
|
||||
'user_id' => $user ? $user->id : null,
|
||||
'client' => [
|
||||
'billing_address' => $this['customer_address'],
|
||||
'billing_name' => $this['customer_name'],
|
||||
'billing_phone_number' => $this['customer_phone'],
|
||||
],
|
||||
'bag' => [
|
||||
'amount' => $this['lines']['data'][0]['amount'],
|
||||
'currency' => $this['lines']['data'][0]['currency'],
|
||||
'type' => $this['lines']['data'][0]['type'],
|
||||
'description' => $this['lines']['data'][0]['description'],
|
||||
],
|
||||
'seller' => null,
|
||||
]
|
||||
],
|
||||
$this->mergeWhen($user, function () use ($user) {
|
||||
return [
|
||||
'relationships' => [
|
||||
'user' => [
|
||||
'data' => [
|
||||
'id' => (string)$user->id,
|
||||
'type' => 'user',
|
||||
'attributes' => [
|
||||
'name' => $user->name,
|
||||
'avatar' => $user->avatar,
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
}),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use App\User;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class InvoiceResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
$user = User::where('stripe_id', $this->customer)->first();
|
||||
$invoice_items = [];
|
||||
$invoice_subscriptions = [];
|
||||
|
||||
// Format bag
|
||||
foreach ($this->invoiceItems() as $item) {
|
||||
array_push($invoice_items, [
|
||||
'amount' => $item->total(),
|
||||
'description' => $item->description,
|
||||
'currency' => $item->currency,
|
||||
'type' => $item->type,
|
||||
]);
|
||||
}
|
||||
|
||||
// Format bag
|
||||
foreach ($this->subscriptions() as $item) {
|
||||
array_push($invoice_subscriptions, [
|
||||
'amount' => $item->total(),
|
||||
'description' => $item->description,
|
||||
'currency' => $item->currency,
|
||||
'type' => $item->type,
|
||||
]);
|
||||
}
|
||||
|
||||
return [
|
||||
'data' => [
|
||||
'id' => $this->id,
|
||||
'type' => 'invoices',
|
||||
'attributes' => [
|
||||
'customer' => $this->customer,
|
||||
'total' => $this->total(),
|
||||
'currency' => $this->currency,
|
||||
'created_at_formatted' => format_date($this->date(), '%d. %B. %Y'),
|
||||
'created_at' => $this->created,
|
||||
'order' => $this->number,
|
||||
'user_id' => $user ? $user->id : null,
|
||||
'client' => [
|
||||
'billing_address' => $this->customer_address,
|
||||
'billing_name' => $this->customer_name,
|
||||
'billing_phone_number' => $this->customer_phone,
|
||||
],
|
||||
'seller' => null,
|
||||
'invoice_items' => $invoice_items,
|
||||
'invoice_subscriptions' => $invoice_subscriptions,
|
||||
]
|
||||
],
|
||||
$this->mergeWhen($user, [
|
||||
'relationships' => [
|
||||
'user' => [
|
||||
'data' => [
|
||||
'id' => (string)$user->id,
|
||||
'type' => 'user',
|
||||
'attributes' => [
|
||||
'name' => $user->name,
|
||||
'avatar' => $user->avatar,
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
|
||||
class PaymentCardCollection extends ResourceCollection
|
||||
{
|
||||
public $collects = PaymentCardResource::class;
|
||||
|
||||
/**
|
||||
* Transform the resource collection into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => $this->collection,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class PaymentCardResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => [
|
||||
'id' => (string)$this['id'],
|
||||
'type' => 'payment_method',
|
||||
'attributes' => [
|
||||
'provider' => 'stripe',
|
||||
'card_id' => $this['id'],
|
||||
'brand' => strtolower($this['card']['brand']),
|
||||
'last4' => $this['card']['last4'],
|
||||
'exp_month' => $this['card']['exp_month'],
|
||||
'exp_year' => $this['card']['exp_year'],
|
||||
'created_at' => format_date($this['created_at'], '%d. %B. %Y'),
|
||||
'status' => 'active',
|
||||
'default' => 0,
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class PaymentDefaultCardResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => [
|
||||
'id' => (string)$this['id'],
|
||||
'type' => 'payment_method',
|
||||
'attributes' => [
|
||||
'provider' => 'stripe',
|
||||
'card_id' => $this['id'],
|
||||
'brand' => isset($this['brand']) ? strtolower($this['brand']) : strtolower($this['card']['brand']),
|
||||
'last4' => isset($this['last4']) ? $this['last4'] : $this['card']['last4'],
|
||||
'exp_month' => isset($this['exp_month']) ? $this['exp_month'] : $this['card']['exp_month'],
|
||||
'exp_year' => isset($this['exp_year']) ? $this['exp_year'] : $this['card']['exp_year'],
|
||||
'created_at' => format_date($this['created_at'], '%d. %B. %Y'),
|
||||
'status' => 'active',
|
||||
'default' => 0,
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use Laravel\Cashier\Cashier;
|
||||
use Laravel\Cashier\Subscription;
|
||||
|
||||
class PlanResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
// Get subscribers
|
||||
$subscriber_count = Subscription::where('stripe_plan', $this['plan']['id'])->where('stripe_status', 'active')->get();
|
||||
|
||||
return [
|
||||
'data' => [
|
||||
'id' => $this['plan']['id'],
|
||||
'type' => 'plans',
|
||||
'attributes' => [
|
||||
'subscribers' => $subscriber_count->count(),
|
||||
'status' => $this['plan']['active'] ? 1 : 0,
|
||||
'name' => $this['product']['name'],
|
||||
'description' => $this['product']['description'],
|
||||
'price' => $this['plan']['amount'],
|
||||
'price_formatted' => Cashier::formatAmount($this['plan']['amount']),
|
||||
'capacity_formatted' => format_gigabytes($this['product']['metadata']['capacity']),
|
||||
'capacity' => (int) $this['product']['metadata']['capacity'],
|
||||
'created_at_formatted' => format_date($this['plan']['created']),
|
||||
'created_at' => $this['plan']['created'],
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
|
||||
class PricingCollection extends ResourceCollection
|
||||
{
|
||||
public $collects = PricingResource::class;
|
||||
|
||||
/**
|
||||
* Transform the resource collection into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => $this->collection,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use Laravel\Cashier\Cashier;
|
||||
|
||||
class PricingResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => [
|
||||
'id' => $this['plan']['id'],
|
||||
'type' => 'plans',
|
||||
'attributes' => [
|
||||
'name' => $this['product']['name'],
|
||||
'description' => $this['product']['description'],
|
||||
'price' => Cashier::formatAmount($this['plan']['amount']),
|
||||
'capacity_formatted' => format_gigabytes($this['product']['metadata']['capacity']),
|
||||
'capacity' => (int)$this['product']['metadata']['capacity'],
|
||||
'currency' => config('cashier.currency'),
|
||||
'tax_rates' => $this->get_tax_rates(),
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get plan tax rates
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_tax_rates(): array
|
||||
{
|
||||
$stripe = resolve('App\Services\StripeService');
|
||||
|
||||
$rates_puplic = [];
|
||||
|
||||
// Get tax rates
|
||||
$rates = $stripe->getTaxRates();
|
||||
|
||||
foreach ($rates as $rate) {
|
||||
|
||||
// Continue when is not active
|
||||
if (!$rate['active']) continue;
|
||||
|
||||
// Calculate tax
|
||||
$tax = $this['plan']['amount'] * ($rate['percentage'] / 100);
|
||||
|
||||
array_push($rates_puplic, [
|
||||
'id' => $rate['id'],
|
||||
'active' => $rate['active'],
|
||||
'jurisdiction' => $rate['jurisdiction'],
|
||||
'percentage' => $rate['percentage'],
|
||||
'plan_price_formatted' => Cashier::formatAmount(round($this['plan']['amount'] + $tax)),
|
||||
]);
|
||||
}
|
||||
|
||||
return $rates_puplic;
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use App\Services\StripeService;
|
||||
use App\User;
|
||||
use Cartalyst\Stripe\Api\PaymentMethods;
|
||||
use Faker\Factory;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class UserResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => [
|
||||
'id' => (string)$this->id,
|
||||
'type' => 'user',
|
||||
'attributes' => [
|
||||
'storage_capacity' => $this->settings->storage_capacity,
|
||||
'subscription' => $this->subscribed('main'),
|
||||
'incomplete_payment' => $this->hasIncompletePayment('main') ? route('cashier.payment', $this->subscription('main')->latestPayment()->id) : null,
|
||||
'stripe_customer' => is_null($this->stripe_id) ? false : true,
|
||||
'name' => $this->name,
|
||||
'email' => env('APP_DEMO') ? obfuscate_email($this->email) : $this->email,
|
||||
'avatar' => $this->avatar,
|
||||
'role' => $this->role,
|
||||
'created_at_formatted' => format_date($this->created_at, '%d. %B. %Y'),
|
||||
'created_at' => $this->created_at,
|
||||
'updated_at' => $this->updated_at,
|
||||
]
|
||||
],
|
||||
'relationships' => [
|
||||
'settings' => [
|
||||
'data' => [
|
||||
'id' => (string)$this->settings->id,
|
||||
'type' => 'settings',
|
||||
'attributes' => [
|
||||
'billing_name' => $this->settings->billing_name,
|
||||
'billing_address' => $this->settings->billing_address,
|
||||
'billing_state' => $this->settings->billing_state,
|
||||
'billing_city' => $this->settings->billing_city,
|
||||
'billing_postal_code' => $this->settings->billing_postal_code,
|
||||
'billing_country' => $this->settings->billing_country,
|
||||
'billing_phone_number' => $this->settings->billing_phone_number,
|
||||
]
|
||||
]
|
||||
],
|
||||
'storage' => [
|
||||
'data' => [
|
||||
'id' => '1',
|
||||
'type' => 'storage',
|
||||
'attributes' => $this->storage
|
||||
]
|
||||
],
|
||||
'favourites' => [
|
||||
'data' => [
|
||||
'id' => '1',
|
||||
'type' => 'folders_favourite',
|
||||
'attributes' => [
|
||||
'folders' => $this->favourite_folders->makeHidden(['pivot'])
|
||||
],
|
||||
],
|
||||
],
|
||||
'tree' => [
|
||||
'data' => [
|
||||
'id' => '1',
|
||||
'type' => 'folders_tree',
|
||||
'attributes' => [
|
||||
'folders' => $this->folder_tree
|
||||
],
|
||||
],
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use App\FileManagerFile;
|
||||
use ByteUnits\Metric;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class UserStorageResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
$document_mimetypes = [
|
||||
'pdf', 'numbers', 'xlsx', 'xls', 'txt', 'md', 'rtf', 'pptx', 'ppt', 'odt', 'ods', 'odp', 'epub', 'docx', 'doc', 'csv', 'pages'
|
||||
];
|
||||
|
||||
// Get all images
|
||||
$images = FileManagerFile::where('user_id', $this->id)
|
||||
->where('type', 'image')->get()->map(function ($item) {
|
||||
return (int)$item->getRawOriginal('filesize');
|
||||
})->sum();
|
||||
|
||||
// Get all audios
|
||||
$audios = FileManagerFile::where('user_id', $this->id)
|
||||
->where('type', 'audio')->get()->map(function ($item) {
|
||||
return (int)$item->getRawOriginal('filesize');
|
||||
})->sum();
|
||||
|
||||
// Get all videos
|
||||
$videos = FileManagerFile::where('user_id', $this->id)
|
||||
->where('type', 'video')->get()->map(function ($item) {
|
||||
return (int)$item->getRawOriginal('filesize');
|
||||
})->sum();
|
||||
|
||||
// Get all documents
|
||||
$documents = FileManagerFile::where('user_id', $this->id)
|
||||
->whereIn('mimetype', $document_mimetypes)->get()->map(function ($item) {
|
||||
return (int)$item->getRawOriginal('filesize');
|
||||
})->sum();
|
||||
|
||||
// Get all other files
|
||||
$others = FileManagerFile::where('user_id', $this->id)
|
||||
->whereNotIn('mimetype', $document_mimetypes)
|
||||
->whereNotIn('type', ['audio', 'video', 'image'])
|
||||
->get()->map(function ($item) {
|
||||
return (int)$item->getRawOriginal('filesize');
|
||||
})->sum();
|
||||
|
||||
return [
|
||||
'data' => [
|
||||
'id' => (string)$this->id,
|
||||
'type' => 'storage',
|
||||
'attributes' => [
|
||||
'used' => Metric::bytes($this->used_capacity)->format(),
|
||||
'capacity' => format_gigabytes($this->settings->storage_capacity),
|
||||
'percentage' => (float)get_storage_fill_percentage($this->used_capacity, $this->settings->storage_capacity),
|
||||
],
|
||||
'meta' => [
|
||||
'images' => [
|
||||
'used' => Metric::bytes($images)->format(),
|
||||
'percentage' => (float)get_storage_fill_percentage($images, $this->settings->storage_capacity),
|
||||
],
|
||||
'audios' => [
|
||||
'used' => Metric::bytes($audios)->format(),
|
||||
'percentage' => (float)get_storage_fill_percentage($audios, $this->settings->storage_capacity),
|
||||
],
|
||||
'videos' => [
|
||||
'used' => Metric::bytes($videos)->format(),
|
||||
'percentage' => (float)get_storage_fill_percentage($videos, $this->settings->storage_capacity),
|
||||
],
|
||||
'documents' => [
|
||||
'used' => Metric::bytes($documents)->format(),
|
||||
'percentage' => (float)get_storage_fill_percentage($documents, $this->settings->storage_capacity),
|
||||
],
|
||||
'others' => [
|
||||
'used' => Metric::bytes($others)->format(),
|
||||
'percentage' => (float)get_storage_fill_percentage($others, $this->settings->storage_capacity),
|
||||
],
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class UserSubscription extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
$stripe = resolve('App\Services\StripeService');
|
||||
|
||||
$active_subscription = $this->subscription('main')->asStripeSubscription();
|
||||
|
||||
// Get subscription details
|
||||
$subscription = $stripe->getPlan($this->subscription('main')->stripe_plan);
|
||||
|
||||
// Retrieve the timestamp from Stripe
|
||||
$current_period_end = $active_subscription["current_period_end"];
|
||||
$current_period_start = $active_subscription["current_period_start"];
|
||||
$canceled_at = $active_subscription["canceled_at"];
|
||||
|
||||
return [
|
||||
'data' => [
|
||||
'id' => $subscription['plan']['id'],
|
||||
'type' => 'subscription',
|
||||
'attributes' => [
|
||||
'incomplete' => $this->subscription('main')->incomplete(),
|
||||
'active' => $this->subscription('main')->active(),
|
||||
'canceled' => $this->subscription('main')->cancelled(),
|
||||
'name' => $subscription['product']['name'],
|
||||
'capacity' => (int)$subscription['product']['metadata']['capacity'],
|
||||
'capacity_formatted' => format_gigabytes($subscription['product']['metadata']['capacity']),
|
||||
'slug' => $subscription['plan']['id'],
|
||||
'canceled_at' => format_date($canceled_at, '%d. %B. %Y'),
|
||||
'created_at' => format_date($current_period_start, '%d. %B. %Y'),
|
||||
'ends_at' => format_date($current_period_end, '%d. %B. %Y'),
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Tools;
|
||||
|
||||
use App;
|
||||
use App\Share;
|
||||
use App\FileManagerFile;
|
||||
use App\FileManagerFolder;
|
||||
use App\Http\Requests\FileFunctions\RenameItemRequest;
|
||||
use App\User;
|
||||
use ByteUnits\Metric;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Intervention\Image\ImageManagerStatic as Image;
|
||||
|
||||
|
||||
class Demo
|
||||
{
|
||||
/**
|
||||
* Create new directory
|
||||
*
|
||||
* @param $request
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function create_folder($request)
|
||||
{
|
||||
// Get variables
|
||||
$user_scope = $request->user() ? $request->user()->token()->scopes[0] : 'editor';
|
||||
$name = $request->has('name') ? $request->input('name') : 'New Folder';
|
||||
|
||||
return [
|
||||
'user_id' => 1,
|
||||
'id' => random_int(1000, 9999),
|
||||
'parent_id' => random_int(1000, 9999),
|
||||
'name' => $name,
|
||||
'type' => 'folder',
|
||||
'unique_id' => random_int(1000, 9999),
|
||||
'user_scope' => $user_scope,
|
||||
'items' => '0',
|
||||
'updated_at' => Carbon::now()->format('j M Y \a\t H:i'),
|
||||
'created_at' => Carbon::now()->format('j M Y \a\t H:i'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename item name
|
||||
*
|
||||
* @param RenameItemRequest $request
|
||||
* @param $unique_id
|
||||
* @return mixed
|
||||
*/
|
||||
public static function rename_item($request, $unique_id)
|
||||
{
|
||||
// Get item
|
||||
if ($request->type === 'folder') {
|
||||
|
||||
$item = FileManagerFolder::where('unique_id', $unique_id)
|
||||
->where('user_id', 1)
|
||||
->first();
|
||||
|
||||
} else {
|
||||
|
||||
$item = FileManagerFile::where('unique_id', $unique_id)
|
||||
->where('user_id', 1)
|
||||
->first();
|
||||
}
|
||||
|
||||
if ($item) {
|
||||
$item->name = $request->name;
|
||||
|
||||
return $item;
|
||||
|
||||
} else {
|
||||
|
||||
return [
|
||||
'unique_id' => $request->unique_id,
|
||||
'name' => $request->name,
|
||||
'type' => $request->type,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload file
|
||||
*
|
||||
* @param $request
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function upload($request)
|
||||
{
|
||||
// Get user data
|
||||
$user_scope = $request->user() ? $request->user()->token()->scopes[0] : 'editor';
|
||||
|
||||
// File
|
||||
$file = $request->file('file');
|
||||
$filename = Str::random() . '-' . str_replace(' ', '', $file->getClientOriginalName());
|
||||
$thumbnail = null;
|
||||
$filesize = $file->getSize();
|
||||
$filetype = get_file_type($file->getMimeType());
|
||||
|
||||
return [
|
||||
'id' => random_int(1000, 9999),
|
||||
'unique_id' => random_int(1000, 9999),
|
||||
'folder_id' => $request->parent_id,
|
||||
'thumbnail' => 'data:' . $request->file('file')->getMimeType() . ';base64, ' . base64_encode(file_get_contents($request->file('file'))),
|
||||
'name' => $file->getClientOriginalName(),
|
||||
'basename' => $filename,
|
||||
'mimetype' => $file->getClientOriginalExtension(),
|
||||
'filesize' => Metric::bytes($filesize)->format(),
|
||||
'type' => $filetype,
|
||||
'file_url' => 'https://vuefilemanager.hi5ve.digital/assets/vue-file-manager-preview.jpg',
|
||||
'user_scope' => $user_scope,
|
||||
'created_at' => Carbon::now()->format('j M Y \a\t H:i'),
|
||||
'updated_at' => Carbon::now()->format('j M Y \a\t H:i'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return 204 status
|
||||
*
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public static function response_204() {
|
||||
|
||||
return response('Done!', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return 204 status
|
||||
*
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public static function favourites($user) {
|
||||
|
||||
return $user->favourite_folders->makeHidden(['pivot']);
|
||||
}
|
||||
}
|
||||
@@ -1,487 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Tools;
|
||||
|
||||
use App;
|
||||
use App\Share;
|
||||
use App\FileManagerFile;
|
||||
use App\FileManagerFolder;
|
||||
use App\Http\Requests\FileFunctions\RenameItemRequest;
|
||||
use App\User;
|
||||
use Aws\Exception\MultipartUploadException;
|
||||
use Aws\S3\MultipartUploader;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Intervention\Image\ImageManagerStatic as Image;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
|
||||
|
||||
class Editor
|
||||
{
|
||||
/**
|
||||
* Create new directory
|
||||
*
|
||||
* @param $request
|
||||
* @param null $shared
|
||||
* @return FileManagerFolder|\Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public static function create_folder($request, $shared = null)
|
||||
{
|
||||
// Get variables
|
||||
$user_scope = is_null($shared) ? $request->user()->token()->scopes[0] : 'editor';
|
||||
$name = $request->has('name') ? $request->input('name') : 'New Folder';
|
||||
$user_id = is_null($shared) ? Auth::id() : $shared->user_id;
|
||||
$unique_id = get_unique_id();
|
||||
|
||||
// Create folder
|
||||
$folder = FileManagerFolder::create([
|
||||
'parent_id' => $request->parent_id,
|
||||
'unique_id' => $unique_id,
|
||||
'user_scope' => $user_scope,
|
||||
'user_id' => $user_id,
|
||||
'type' => 'folder',
|
||||
'name' => $name,
|
||||
]);
|
||||
|
||||
// Return new folder
|
||||
return $folder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename item name
|
||||
*
|
||||
* @param RenameItemRequest $request
|
||||
* @param $unique_id
|
||||
* @param null $shared
|
||||
* @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function rename_item($request, $unique_id, $shared = null)
|
||||
{
|
||||
// Get user id
|
||||
$user_id = is_null($shared) ? Auth::id() : $shared->user_id;
|
||||
|
||||
// Get item
|
||||
$item = get_item($request->type, $unique_id, $user_id);
|
||||
|
||||
// Rename item
|
||||
$item->update([
|
||||
'name' => $request->name
|
||||
]);
|
||||
|
||||
// Return updated item
|
||||
return $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete file or folder
|
||||
*
|
||||
* @param $request
|
||||
* @param $unique_id
|
||||
* @param null $shared
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function delete_item($request, $unique_id, $shared = null)
|
||||
{
|
||||
// Get user id
|
||||
$user = is_null($shared) ? Auth::user() : User::findOrFail($shared->user_id);
|
||||
|
||||
// Delete folder
|
||||
if ($request->input('data.type') === 'folder') {
|
||||
|
||||
// Get folder
|
||||
$folder = FileManagerFolder::withTrashed()
|
||||
->with(['folders'])
|
||||
->where('user_id', $user->id)
|
||||
->where('unique_id', $unique_id)
|
||||
->first();
|
||||
|
||||
// Get folder shared record
|
||||
$shared = Share::where('user_id', $user->id)
|
||||
->where('type', '=', 'folder')
|
||||
->where('item_id', $unique_id)
|
||||
->first();
|
||||
|
||||
// Delete folder shared record
|
||||
if ($shared) {
|
||||
$shared->delete();
|
||||
}
|
||||
|
||||
// Force delete children files
|
||||
if ($request->input('data.force_delete')) {
|
||||
|
||||
// Get children folder ids
|
||||
$child_folders = filter_folders_ids($folder->trashed_folders, 'unique_id');
|
||||
|
||||
// Get children files
|
||||
$files = FileManagerFile::onlyTrashed()
|
||||
->where('user_id', $user->id)
|
||||
->whereIn('folder_id', Arr::flatten([$unique_id, $child_folders]))
|
||||
->get();
|
||||
|
||||
// Remove all children files
|
||||
foreach ($files as $file) {
|
||||
|
||||
// Delete file
|
||||
Storage::delete('/file-manager/' . $file->basename);
|
||||
|
||||
// Delete thumbnail if exist
|
||||
if (!is_null($file->thumbnail)) Storage::delete('/file-manager/' . $file->getRawOriginal('thumbnail'));
|
||||
|
||||
// Delete file permanently
|
||||
$file->forceDelete();
|
||||
}
|
||||
|
||||
// Delete folder record
|
||||
$folder->forceDelete();
|
||||
}
|
||||
|
||||
// Soft delete items
|
||||
if (!$request->input('data.force_delete')) {
|
||||
|
||||
// Remove folder from user favourites
|
||||
$user->favourite_folders()->detach($unique_id);
|
||||
|
||||
// Soft delete folder record
|
||||
$folder->delete();
|
||||
}
|
||||
}
|
||||
|
||||
// Delete item
|
||||
if ($request->input('data.type') !== 'folder') {
|
||||
|
||||
// Get file
|
||||
$file = FileManagerFile::withTrashed()
|
||||
->where('user_id', $user->id)
|
||||
->where('unique_id', $unique_id)
|
||||
->first();
|
||||
|
||||
// Get folder shared record
|
||||
$shared = Share::where('user_id', $user->id)
|
||||
->where('type', '=', 'file')
|
||||
->where('item_id', $unique_id)
|
||||
->first();
|
||||
|
||||
// Delete file shared record
|
||||
if ($shared) {
|
||||
$shared->delete();
|
||||
}
|
||||
|
||||
// Force delete file
|
||||
if ($request->input('data.force_delete')) {
|
||||
|
||||
// Delete file
|
||||
Storage::delete('/file-manager/' . $file->basename);
|
||||
|
||||
// Delete thumbnail if exist
|
||||
if ($file->thumbnail) Storage::delete('/file-manager/' . $file->getRawOriginal('thumbnail'));
|
||||
|
||||
// Delete file permanently
|
||||
$file->forceDelete();
|
||||
}
|
||||
|
||||
// Soft delete file
|
||||
if (!$request->input('data.force_delete')) {
|
||||
|
||||
// Soft delete file
|
||||
$file->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move folder or file to new location
|
||||
*
|
||||
* @param $request
|
||||
* @param $unique_id
|
||||
* @param null $shared
|
||||
*/
|
||||
public static function move($request, $unique_id, $shared = null)
|
||||
{
|
||||
// Get user id
|
||||
$user_id = is_null($shared) ? Auth::id() : $shared->user_id;
|
||||
|
||||
if ($request->from_type === 'folder') {
|
||||
|
||||
// Move folder
|
||||
$item = FileManagerFolder::where('user_id', $user_id)
|
||||
->where('unique_id', $unique_id)
|
||||
->firstOrFail();
|
||||
|
||||
$item->update([
|
||||
'parent_id' => $request->to_unique_id
|
||||
]);
|
||||
|
||||
} else {
|
||||
|
||||
// Move file under new folder
|
||||
$item = FileManagerFile::where('user_id', $user_id)
|
||||
->where('unique_id', $unique_id)
|
||||
->firstOrFail();
|
||||
|
||||
$item->update([
|
||||
'folder_id' => $request->to_unique_id
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload file
|
||||
*
|
||||
* @param $request
|
||||
* @param null $shared
|
||||
* @return FileManagerFile|\Illuminate\Database\Eloquent\Model
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function upload($request, $shared = null)
|
||||
{
|
||||
// Get parent_id from request
|
||||
$file = $request->file('file');
|
||||
|
||||
// Check or create directories
|
||||
self::check_directories(['chunks', 'file-manager']);
|
||||
|
||||
// File name
|
||||
$user_file_name = basename('chunks/' . substr($file->getClientOriginalName(), 17), '.part');
|
||||
$disk_file_name = basename('chunks/' . $file->getClientOriginalName(), '.part');
|
||||
$temp_filename = $file->getClientOriginalName();
|
||||
|
||||
// Generate file
|
||||
File::append(config('filesystems.disks.local.root') . '/chunks/' . $temp_filename, $file->get());
|
||||
|
||||
// If last then process file
|
||||
if ($request->boolean('is_last')) {
|
||||
|
||||
$disk_local = Storage::disk('local');
|
||||
$unique_id = get_unique_id();
|
||||
|
||||
// Get user data
|
||||
$user_scope = is_null($shared) ? $request->user()->token()->scopes[0] : 'editor';
|
||||
$user_id = is_null($shared) ? Auth::id() : $shared->user_id;
|
||||
|
||||
// File Info
|
||||
$file_size = $disk_local->size('chunks/' . $temp_filename);
|
||||
$file_mimetype = $disk_local->mimeType('chunks/' . $temp_filename);
|
||||
|
||||
// Check if user has enough space to upload file
|
||||
self::check_user_storage_capacity($user_id, $file_size, $temp_filename);
|
||||
|
||||
// Create thumbnail
|
||||
$thumbnail = self::get_image_thumbnail('chunks/' . $temp_filename, $disk_file_name);
|
||||
|
||||
// Move finished file from chunk to file-manager directory
|
||||
$disk_local->move('chunks/' . $temp_filename, 'file-manager/' . $disk_file_name);
|
||||
|
||||
// Move files to external storage
|
||||
if (!is_storage_driver(['local'])) {
|
||||
|
||||
// Clear failed uploads if exists
|
||||
self::clear_failed_files();
|
||||
|
||||
// Move file to external storage service
|
||||
self::move_to_external_storage($disk_file_name, $thumbnail);
|
||||
}
|
||||
|
||||
// Store file
|
||||
$options = [
|
||||
'mimetype' => get_file_type_from_mimetype($file_mimetype),
|
||||
'type' => get_file_type($file_mimetype),
|
||||
'folder_id' => $request->parent_id,
|
||||
'name' => $user_file_name,
|
||||
'unique_id' => $unique_id,
|
||||
'basename' => $disk_file_name,
|
||||
'user_scope' => $user_scope,
|
||||
'thumbnail' => $thumbnail,
|
||||
'filesize' => $file_size,
|
||||
'user_id' => $user_id,
|
||||
];
|
||||
|
||||
// Return new file
|
||||
return FileManagerFile::create($options);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear failed files
|
||||
*/
|
||||
private static function clear_failed_files()
|
||||
{
|
||||
$local_disk = Storage::disk('local');
|
||||
|
||||
// Get all files from storage
|
||||
$files = collect([
|
||||
$local_disk->allFiles('file-manager'),
|
||||
$local_disk->allFiles('chunks')
|
||||
])->collapse();
|
||||
|
||||
$files->each(function ($file) use ($local_disk) {
|
||||
|
||||
// Get the file's last modification time.
|
||||
$last_modified = $local_disk->lastModified($file);
|
||||
|
||||
// Get diffInHours
|
||||
$diff = Carbon::parse($last_modified)->diffInHours(Carbon::now());
|
||||
|
||||
// Delete if file is in local storage more than 24 hours
|
||||
if ($diff > 24) {
|
||||
|
||||
Log::info('Failed file or chunk ' . $file . ' deleted.');
|
||||
|
||||
// Delete file from local storage
|
||||
$local_disk->delete($file);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Move file to external storage if is set
|
||||
*
|
||||
* @param string $filename
|
||||
* @param string|null $thumbnail
|
||||
*/
|
||||
private static function move_to_external_storage(string $filename, ?string $thumbnail): void
|
||||
{
|
||||
$disk_local = Storage::disk('local');
|
||||
|
||||
foreach ([$filename, $thumbnail] as $file) {
|
||||
|
||||
// Check if file exist
|
||||
if (!$file) continue;
|
||||
|
||||
// Get file size
|
||||
$filesize = $disk_local->size('file-manager/' . $file);
|
||||
|
||||
// If file is bigger than 5.2MB then run multipart upload
|
||||
if ($filesize > 5242880) {
|
||||
|
||||
// Get driver
|
||||
$driver = \Storage::getDriver();
|
||||
|
||||
// Get adapter
|
||||
$adapter = $driver->getAdapter();
|
||||
|
||||
// Get client
|
||||
$client = $adapter->getClient();
|
||||
|
||||
// Prepare the upload parameters.
|
||||
$uploader = new MultipartUploader($client, config('filesystems.disks.local.root') . '/file-manager/' . $file, [
|
||||
'bucket' => $adapter->getBucket(),
|
||||
'key' => 'file-manager/' . $file
|
||||
]);
|
||||
|
||||
try {
|
||||
|
||||
// Upload content
|
||||
$uploader->upload();
|
||||
|
||||
} catch (MultipartUploadException $e) {
|
||||
|
||||
// Write error log
|
||||
Log::error($e->getMessage());
|
||||
|
||||
// Delete file after error
|
||||
$disk_local->delete('file-manager/' . $file);
|
||||
|
||||
throw new HttpException(409, $e->getMessage());
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Stream file object to s3
|
||||
Storage::putFileAs('file-manager', config('filesystems.disks.local.root') . '/file-manager/' . $file, $file, 'private');
|
||||
}
|
||||
|
||||
// Delete file after upload
|
||||
$disk_local->delete('file-manager/' . $file);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if directories 'chunks' and 'file-manager exist', if no, then create
|
||||
*
|
||||
* @param $directories
|
||||
*/
|
||||
private static function check_directories($directories): void
|
||||
{
|
||||
foreach ($directories as $directory) {
|
||||
|
||||
if (!Storage::disk('local')->exists($directory)) {
|
||||
Storage::disk('local')->makeDirectory($directory);
|
||||
}
|
||||
|
||||
if (!is_storage_driver(['local'])) {
|
||||
if (!Storage::exists($directory)) {
|
||||
Storage::makeDirectory($directory);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create thumbnail for images
|
||||
*
|
||||
* @param string $file_path
|
||||
* @param string $filename
|
||||
* @param $file
|
||||
* @return string|null
|
||||
*/
|
||||
private static function get_image_thumbnail(string $file_path, string $filename)
|
||||
{
|
||||
$local_disk = Storage::disk('local');
|
||||
|
||||
// Create thumbnail from image
|
||||
if (in_array($local_disk->mimeType($file_path), ['image/gif', 'image/jpeg', 'image/jpg', 'image/png', 'image/webp'])) {
|
||||
|
||||
// Get thumbnail name
|
||||
$thumbnail = 'thumbnail-' . $filename;
|
||||
|
||||
// Create intervention image
|
||||
$image = Image::make(config('filesystems.disks.local.root') . '/' . $file_path)->orientate();
|
||||
|
||||
// Resize image
|
||||
$image->resize(512, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
})->stream();
|
||||
|
||||
// Store thumbnail to disk
|
||||
$local_disk->put('file-manager/' . $thumbnail, $image);
|
||||
}
|
||||
|
||||
// Return thumbnail as svg file
|
||||
if ($local_disk->mimeType($file_path) === 'image/svg+xml') {
|
||||
|
||||
$thumbnail = $filename;
|
||||
}
|
||||
|
||||
return $thumbnail ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user has enough space to upload file
|
||||
*
|
||||
* @param $user_id
|
||||
* @param int $file_size
|
||||
* @param $temp_filename
|
||||
*/
|
||||
private static function check_user_storage_capacity($user_id, int $file_size, $temp_filename): void
|
||||
{
|
||||
// Get user storage percentage and get storage_limitation setting
|
||||
$user_storage_used = user_storage_percentage($user_id, $file_size);
|
||||
$storage_limitation = get_setting('storage_limitation');
|
||||
|
||||
// Check if user can upload
|
||||
if ($storage_limitation && $user_storage_used >= 100) {
|
||||
|
||||
// Delete file
|
||||
Storage::disk('local')->delete('chunks/' . $temp_filename);
|
||||
|
||||
// Abort uploading
|
||||
abort(423, 'You exceed your storage limit!');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* App\Invoice
|
||||
*
|
||||
* @property int $id
|
||||
* @property string $token
|
||||
* @property string $order
|
||||
* @property string|null $provider
|
||||
* @property string $user_id
|
||||
* @property string $plan_id
|
||||
* @property array $seller
|
||||
* @property array $client
|
||||
* @property array $bag
|
||||
* @property string|null $notes
|
||||
* @property string $total
|
||||
* @property string $currency
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property-read \App\User|null $user
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice query()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereBag($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereClient($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereCreatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereCurrency($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereNotes($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereOrder($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice wherePlanId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereProvider($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereSeller($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereToken($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereTotal($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereUpdatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereUserId($value)
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class Invoice extends Model
|
||||
{
|
||||
protected $guarded = [
|
||||
'id'
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'seller' => 'array',
|
||||
'client' => 'array',
|
||||
'bag' => 'array',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get user instance
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasOne
|
||||
*/
|
||||
public function user() {
|
||||
return $this->hasOne(User::class, 'id', 'user_id');
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class ResetPassword extends Notification
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($token)
|
||||
{
|
||||
$this->token = $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification's delivery channels.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function via($notifiable)
|
||||
{
|
||||
return ['mail'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return \Illuminate\Notifications\Messages\MailMessage
|
||||
*/
|
||||
public function toMail($notifiable)
|
||||
{
|
||||
$reset_url = url('/create-new-password?token=' . $this->token);
|
||||
|
||||
return (new MailMessage)
|
||||
->subject(__('vuefilemanager.reset_password_subject') . config('vuefilemanager.app_name'))
|
||||
->greeting(__('vuefilemanager.reset_password_greeting'))
|
||||
->line(__('vuefilemanager.reset_password_line_1'))
|
||||
->action(__('vuefilemanager.reset_password_action'), $reset_url)
|
||||
->line(__('vuefilemanager.reset_password_line_2'))
|
||||
->salutation(__('vuefilemanager.salutation') . ', ' . config('vuefilemanager.app_name'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($notifiable)
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
}
|
||||
45
app/Page.php
45
app/Page.php
@@ -1,45 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Kyslik\ColumnSortable\Sortable;
|
||||
|
||||
/**
|
||||
* App\Page
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $visibility
|
||||
* @property string $title
|
||||
* @property string $slug
|
||||
* @property string $content
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Page newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Page newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Page query()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Page sortable($defaultParameters = null)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Page whereContent($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Page whereId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Page whereSlug($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Page whereTitle($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Page whereVisibility($value)
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class Page extends Model
|
||||
{
|
||||
use Sortable;
|
||||
|
||||
/**
|
||||
* Sortable columns
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
public $sortable = [
|
||||
'title',
|
||||
'slug',
|
||||
'visibility',
|
||||
];
|
||||
|
||||
public $timestamps = false;
|
||||
|
||||
protected $guarded = ['id'];
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* App\PaymentGateway
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $status
|
||||
* @property int $sandbox
|
||||
* @property string $name
|
||||
* @property string $slug
|
||||
* @property string $logo
|
||||
* @property string|null $client_id
|
||||
* @property string|null $secret
|
||||
* @property string|null $webhook
|
||||
* @property string|null $optional
|
||||
* @property int|null $payment_processed
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway query()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway whereClientId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway whereId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway whereLogo($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway whereName($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway whereOptional($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway wherePaymentProcessed($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway whereSandbox($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway whereSecret($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway whereSlug($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway whereStatus($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway whereWebhook($value)
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class PaymentGateway extends Model
|
||||
{
|
||||
protected $guarded = ['id'];
|
||||
|
||||
public $timestamps = false;
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Laravel\Passport\Console\ClientCommand;
|
||||
use Laravel\Passport\Console\InstallCommand;
|
||||
use Laravel\Passport\Console\KeysCommand;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register any application services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap any application services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
Schema::defaultStringLength(191);
|
||||
|
||||
$get_time_locale = App::getLocale() . '_' . mb_strtoupper(App::getLocale());
|
||||
|
||||
// Set locale for carbon dates
|
||||
setlocale(LC_TIME, $get_time_locale);
|
||||
|
||||
// Install passport commands
|
||||
$this->commands([
|
||||
InstallCommand::class,
|
||||
ClientCommand::class,
|
||||
KeysCommand::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Laravel\Passport\Passport;
|
||||
|
||||
class AuthServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* The policy mappings for the application.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $policies = [
|
||||
// 'App\Model' => 'App\Policies\ModelPolicy',
|
||||
];
|
||||
|
||||
/**
|
||||
* Register any authentication / authorization services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
$this->registerPolicies();
|
||||
|
||||
// Define admin settings gate
|
||||
Gate::define('admin-settings', function ($user) {
|
||||
return $user->role === 'admin';
|
||||
});
|
||||
|
||||
Passport::routes();
|
||||
|
||||
Passport::tokensCan([
|
||||
'master' => 'Master',
|
||||
'editor' => 'Editor',
|
||||
'visitor' => 'Visitor',
|
||||
]);
|
||||
|
||||
Passport::setDefaultScope([
|
||||
'master',
|
||||
'editor',
|
||||
'visitor',
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
class RouteServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* This namespace is applied to your controller routes.
|
||||
*
|
||||
* In addition, it is set as the URL generator's root namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'App\Http\Controllers';
|
||||
|
||||
/**
|
||||
* The path to the "home" route for your application.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public const HOME = '/home';
|
||||
|
||||
/**
|
||||
* Define your route model bindings, pattern filters, etc.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
//
|
||||
|
||||
parent::boot();
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the routes for the application.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function map()
|
||||
{
|
||||
$this->mapApiRoutes();
|
||||
|
||||
$this->mapWebRoutes();
|
||||
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the "web" routes for the application.
|
||||
*
|
||||
* These routes all receive session state, CSRF protection, etc.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function mapWebRoutes()
|
||||
{
|
||||
Route::middleware('web')
|
||||
->namespace($this->namespace)
|
||||
->group(base_path('routes/web.php'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the "api" routes for the application.
|
||||
*
|
||||
* These routes are typically stateless.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function mapApiRoutes()
|
||||
{
|
||||
Route::prefix('api')
|
||||
->middleware('api')
|
||||
->namespace($this->namespace)
|
||||
->group(base_path('routes/api.php'));
|
||||
}
|
||||
}
|
||||
@@ -1,387 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\User;
|
||||
use Artisan;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
use Laravel\Cashier\Exceptions\IncompletePayment;
|
||||
use Laravel\Cashier\Exceptions\PaymentActionRequired;
|
||||
use Stripe;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
|
||||
class StripeService
|
||||
{
|
||||
/**
|
||||
* Stripe Service constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->stripe = Stripe::make(config('cashier.secret'), '2020-03-02');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Stripe account details
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAccountDetails()
|
||||
{
|
||||
$account = $this->stripe->account()->details();
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get setup intent
|
||||
*
|
||||
* @param $user
|
||||
* @return mixed
|
||||
*/
|
||||
public function getSetupIntent($user)
|
||||
{
|
||||
// Create stripe customer if not exist
|
||||
$user->createOrGetStripeCustomer();
|
||||
|
||||
// Return setup intent
|
||||
return $user->createSetupIntent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tax rate ids
|
||||
* @return array
|
||||
*/
|
||||
public function getTaxRates()
|
||||
{
|
||||
$tax_rates = $this->stripe->taxRates()->all();
|
||||
|
||||
return $tax_rates['data'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default payment option or set new default payment
|
||||
*
|
||||
* @param $request
|
||||
* @param $user
|
||||
* @return mixed
|
||||
*/
|
||||
public function getOrSetDefaultPaymentMethod($request, $user)
|
||||
{
|
||||
// Check payment method
|
||||
if (!$request->has('payment.meta.pm') && $user->hasDefaultPaymentMethod()) {
|
||||
|
||||
// Get default payment
|
||||
return $user->defaultPaymentMethod()->paymentMethod;
|
||||
}
|
||||
|
||||
// Clear cached payment methods
|
||||
cache_forget_many([
|
||||
'payment-methods-user-' . $user->id,
|
||||
'default-payment-methods-user-' . $user->id
|
||||
]);
|
||||
|
||||
if ($request->has('payment.meta.pm') && $user->hasDefaultPaymentMethod()) {
|
||||
|
||||
// Set new payment
|
||||
return $user->addPaymentMethod($request->input('payment.meta.pm'))->paymentMethod;
|
||||
|
||||
} else if ($request->has('payment.meta.pm') && !$user->hasDefaultPaymentMethod()) {
|
||||
|
||||
// Set new payment
|
||||
return $user->updateDefaultPaymentMethod($request->input('payment.meta.pm'))->paymentMethod;
|
||||
|
||||
} else {
|
||||
|
||||
throw new HttpException(400, 'Something went wrong.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register new payment method
|
||||
*
|
||||
* @param $request
|
||||
* @param $user
|
||||
* @return mixed
|
||||
*/
|
||||
public function registerNewPaymentMethod($request, $user)
|
||||
{
|
||||
// Clear cached payment methods
|
||||
cache_forget_many([
|
||||
'payment-methods-user-' . $user->id,
|
||||
'default-payment-methods-user-' . $user->id
|
||||
]);
|
||||
|
||||
// Set new payment method
|
||||
$user->addPaymentMethod($request->token)->paymentMethod;
|
||||
|
||||
// Set new default payment
|
||||
if ($request->default) {
|
||||
$user->updateDefaultPaymentMethod($request->token)->paymentMethod;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new subscription or replace by new subscription
|
||||
*
|
||||
* @param $request
|
||||
* @param $user
|
||||
* @param $paymentMethod
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function createOrReplaceSubscription($request, $user)
|
||||
{
|
||||
try {
|
||||
|
||||
// Get payment method
|
||||
$paymentMethod = $this->getOrSetDefaultPaymentMethod($request, $user);
|
||||
|
||||
// Check if user have subscription
|
||||
if ($user->subscribed('main')) {
|
||||
|
||||
// Change subscription plan
|
||||
$user->subscription('main')->skipTrial()->swap($request->input('plan.data.id'));
|
||||
|
||||
} else {
|
||||
|
||||
// Create subscription
|
||||
$user->newSubscription('main', $request->input('plan.data.id'))->create($paymentMethod);
|
||||
}
|
||||
|
||||
} catch (IncompletePayment $exception) {
|
||||
|
||||
if ($exception instanceof PaymentActionRequired) {
|
||||
|
||||
$cashier_route = route('cashier.payment', [$exception->payment->id, 'redirect' => url('/settings/subscription')]);
|
||||
|
||||
throw new HttpException(402, $cashier_route);
|
||||
} else {
|
||||
throw new HttpException(400, $exception->getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update customer details
|
||||
*
|
||||
* @param $user
|
||||
*/
|
||||
public function updateCustomerDetails($user)
|
||||
{
|
||||
$user->updateStripeCustomer([
|
||||
'name' => $user->settings->billing_name,
|
||||
'phone' => $user->settings->billing_phone_number,
|
||||
'address' => [
|
||||
'line1' => $user->settings->billing_address,
|
||||
'city' => $user->settings->billing_city,
|
||||
'country' => $user->settings->billing_country,
|
||||
'postal_code' => $user->settings->billing_postal_code,
|
||||
'state' => $user->settings->billing_state,
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all plans
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPlans()
|
||||
{
|
||||
// Get stripe plans
|
||||
$stripe_plans = $this->stripe->plans()->all();
|
||||
|
||||
// Plans container
|
||||
$plans = [];
|
||||
|
||||
foreach ($stripe_plans['data'] as $plan) {
|
||||
|
||||
// Get stripe product
|
||||
$product = $this->stripe->products()->find($plan['product']);
|
||||
|
||||
// Push data to $plan container
|
||||
if ($product['active'] && isset($product['metadata']['capacity'])) {
|
||||
array_push($plans, [
|
||||
'plan' => $plan,
|
||||
'product' => $product,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
return $plans;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all active plans
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getActivePlans()
|
||||
{
|
||||
// Get stripe plans
|
||||
$stripe_plans = $this->stripe->plans()->all();
|
||||
|
||||
// Plans container
|
||||
$plans = [];
|
||||
|
||||
foreach ($stripe_plans['data'] as $plan) {
|
||||
|
||||
if ($plan['active']) {
|
||||
|
||||
// Get stripe product
|
||||
$product = $this->stripe->products()->find($plan['product']);
|
||||
|
||||
// Push data to $plan container
|
||||
if ($product['active'] && isset($product['metadata']['capacity'])) {
|
||||
array_push($plans, [
|
||||
'plan' => $plan,
|
||||
'product' => $product,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $plans;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get plan details
|
||||
*
|
||||
* @param $id
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPlan($id)
|
||||
{
|
||||
$plan = $this->stripe->plans()->find($id);
|
||||
$product = $this->stripe->products()->find($plan['product']);
|
||||
|
||||
return compact('plan', 'product');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create plan
|
||||
*
|
||||
* @param $data
|
||||
* @return mixed
|
||||
*/
|
||||
public function createPlan($data)
|
||||
{
|
||||
if ($data instanceof Request) {
|
||||
$plan = [
|
||||
'name' => $data->input('attributes.name'),
|
||||
'description' => $data->input('attributes.description'),
|
||||
'price' => $data->input('attributes.price'),
|
||||
'capacity' => $data->input('attributes.capacity'),
|
||||
];
|
||||
} else {
|
||||
$plan = [
|
||||
'name' => $data['attributes']['name'],
|
||||
'description' => $data['attributes']['description'],
|
||||
'price' => $data['attributes']['price'],
|
||||
'capacity' => $data['attributes']['capacity'],
|
||||
];
|
||||
}
|
||||
|
||||
$product = $this->stripe->products()->create([
|
||||
'name' => $plan['name'],
|
||||
'description' => $plan['description'],
|
||||
'metadata' => [
|
||||
'capacity' => $plan['capacity']
|
||||
]
|
||||
]);
|
||||
|
||||
$plan = $this->stripe->plans()->create([
|
||||
'id' => Str::slug($plan['name']),
|
||||
'amount' => $plan['price'],
|
||||
'currency' => config('cashier.currency'),
|
||||
'interval' => 'month',
|
||||
'product' => $product['id'],
|
||||
]);
|
||||
|
||||
return compact('plan', 'product');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update plan
|
||||
*
|
||||
* @param $request
|
||||
* @param $id
|
||||
*/
|
||||
public function updatePlan($request, $id)
|
||||
{
|
||||
$plan_colls = ['is_active', 'price'];
|
||||
$product_colls = ['name', 'description', 'capacity'];
|
||||
|
||||
$plan = $this->stripe->plans()->find($id);
|
||||
|
||||
// Update product
|
||||
if (in_array($request->name, $product_colls)) {
|
||||
|
||||
if ($request->name === 'capacity') {
|
||||
$this->stripe->products()->update($plan['product'], ['metadata' => ['capacity' => $request->value]]);
|
||||
}
|
||||
if ($request->name === 'name') {
|
||||
$this->stripe->products()->update($plan['product'], ['name' => $request->value]);
|
||||
}
|
||||
if ($request->name === 'description') {
|
||||
$this->stripe->products()->update($plan['product'], ['description' => $request->value]);
|
||||
}
|
||||
}
|
||||
|
||||
// Update plan
|
||||
if (in_array($request->name, $plan_colls)) {
|
||||
|
||||
if ($request->name === 'is_active') {
|
||||
$this->stripe->plans()->update($id, ['active' => $request->value]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete plan
|
||||
*
|
||||
* @param $slug
|
||||
*/
|
||||
public function deletePlan($slug)
|
||||
{
|
||||
$this->stripe->plans()->delete($slug);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all user invoices
|
||||
*
|
||||
* @param $user
|
||||
* @return mixed
|
||||
*/
|
||||
public function getUserInvoices($user)
|
||||
{
|
||||
return $user->invoices();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user invoice by id
|
||||
*
|
||||
* @param $id
|
||||
* @return \Laravel\Cashier\Invoice|null
|
||||
*/
|
||||
public function getUserInvoice($customer, $id)
|
||||
{
|
||||
$user = User::where('stripe_id', $customer)->firstOrFail();
|
||||
|
||||
return $user->findInvoice($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all invoices
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getInvoices()
|
||||
{
|
||||
return $this->stripe->invoices()->all([
|
||||
'limit' => 20
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* App\Setting
|
||||
*
|
||||
* @property int $id
|
||||
* @property string $name
|
||||
* @property string|null $value
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Setting newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Setting newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Setting query()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Setting whereId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Setting whereName($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Setting whereValue($value)
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class Setting extends Model
|
||||
{
|
||||
public $timestamps = false;
|
||||
|
||||
protected $guarded = ['id'];
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* App\Share
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $user_id
|
||||
* @property string $token
|
||||
* @property int $item_id
|
||||
* @property string $type
|
||||
* @property string|null $permission
|
||||
* @property int $protected
|
||||
* @property string|null $password
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property-read string $link
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Share newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Share newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Share query()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Share whereCreatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Share whereId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Share whereItemId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Share wherePassword($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Share wherePermission($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Share whereProtected($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Share whereToken($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Share whereType($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Share whereUpdatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Share whereUserId($value)
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class Share extends Model
|
||||
{
|
||||
protected $guarded = ['id'];
|
||||
|
||||
protected $appends = ['link'];
|
||||
|
||||
/**
|
||||
* Generate share link
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLinkAttribute() {
|
||||
|
||||
return url('/shared', ['token' => $this->attributes['token']]);
|
||||
}
|
||||
}
|
||||
304
app/User.php
304
app/User.php
@@ -1,304 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use App\Notifications\ResetPassword;
|
||||
use App\Notifications\ResetUserPasswordNotification;
|
||||
use ByteUnits\Metric;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Laravel\Cashier\Billable;
|
||||
use Laravel\Passport\HasApiTokens;
|
||||
use Kyslik\ColumnSortable\Sortable;
|
||||
use Rinvex\Subscriptions\Traits\HasSubscriptions;
|
||||
|
||||
/**
|
||||
* App\User
|
||||
*
|
||||
* @property int $id
|
||||
* @property string $name
|
||||
* @property string $email
|
||||
* @property \Illuminate\Support\Carbon|null $email_verified_at
|
||||
* @property string $password
|
||||
* @property \Illuminate\Contracts\Routing\UrlGenerator|string $avatar
|
||||
* @property string|null $remember_token
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\Laravel\Passport\Client[] $clients
|
||||
* @property-read int|null $clients_count
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\FileManagerFolder[] $favourites
|
||||
* @property-read int|null $favourites_count
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\FileManagerFile[] $files
|
||||
* @property-read int|null $files_count
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\FileManagerFile[] $files_with_trashed
|
||||
* @property-read int|null $files_with_trashed_count
|
||||
* @property-read mixed $used_capacity
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\FileManagerFile[] $latest_uploads
|
||||
* @property-read int|null $latest_uploads_count
|
||||
* @property-read \Illuminate\Notifications\DatabaseNotificationCollection|\Illuminate\Notifications\DatabaseNotification[] $notifications
|
||||
* @property-read int|null $notifications_count
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\Laravel\Passport\Token[] $tokens
|
||||
* @property-read int|null $tokens_count
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User query()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereAvatar($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereCreatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereEmail($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereEmailVerifiedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereName($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User wherePassword($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereRememberToken($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereUpdatedAt($value)
|
||||
* @mixin \Eloquent
|
||||
* @property string $role
|
||||
* @property string|null $stripe_id
|
||||
* @property string|null $card_brand
|
||||
* @property string|null $card_last_four
|
||||
* @property string|null $trial_ends_at
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\FileManagerFolder[] $favourite_folders
|
||||
* @property-read int|null $favourite_folders_count
|
||||
* @property-read mixed $folder_tree
|
||||
* @property-read mixed $storage
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Invoice[] $invoices
|
||||
* @property-read int|null $invoices_count
|
||||
* @property-read int|null $payment_cards_count
|
||||
* @property-read \App\UserSettings|null $settings
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\Laravel\Cashier\Subscription[] $subscriptions
|
||||
* @property-read int|null $subscriptions_count
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereCardBrand($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereCardLastFour($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereRole($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereStripeId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereTrialEndsAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User sortable($defaultParameters = null)
|
||||
*/
|
||||
class User extends Authenticatable
|
||||
{
|
||||
use HasApiTokens, Notifiable, Billable, Sortable;
|
||||
|
||||
protected $guarded = ['id', 'role'];
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name', 'email', 'password', 'avatar',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be hidden for arrays.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $hidden = [
|
||||
'password', 'remember_token',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = [
|
||||
'email_verified_at' => 'datetime',
|
||||
];
|
||||
|
||||
protected $appends = [
|
||||
'used_capacity', 'storage'
|
||||
];
|
||||
|
||||
/**
|
||||
* Sortable columns
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
public $sortable = [
|
||||
'id',
|
||||
'name',
|
||||
'role',
|
||||
'created_at',
|
||||
'storage_capacity',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get tax rate id for user
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function taxRates()
|
||||
{
|
||||
$stripe = resolve('App\Services\StripeService');
|
||||
|
||||
// Get tax rates
|
||||
$rates = collect($stripe->getTaxRates());
|
||||
|
||||
// Find tax rate
|
||||
$user_tax_rate = $rates->first(function ($item) {
|
||||
return $item['jurisdiction'] === $this->settings->billing_country && $item['active'];
|
||||
});
|
||||
|
||||
return $user_tax_rate ? [$user_tax_rate['id']] : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user used storage details
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getStorageAttribute()
|
||||
{
|
||||
// Get storage limitation setup
|
||||
$storage_limitation = get_setting('storage_limitation');
|
||||
$is_storage_limit = $storage_limitation ? $storage_limitation : 1;
|
||||
|
||||
// Get user storage usage
|
||||
if (! $is_storage_limit) {
|
||||
|
||||
return [
|
||||
'used' => $this->used_capacity,
|
||||
'used_formatted' => Metric::bytes($this->used_capacity)->format(),
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'used' => (float)get_storage_fill_percentage($this->used_capacity, $this->settings->storage_capacity),
|
||||
'used_formatted' => get_storage_fill_percentage($this->used_capacity, $this->settings->storage_capacity) . '%',
|
||||
'capacity' => $this->settings->storage_capacity,
|
||||
'capacity_formatted' => format_gigabytes($this->settings->storage_capacity),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user used storage capacity in bytes
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getUsedCapacityAttribute()
|
||||
{
|
||||
$user_capacity = $this->files_with_trashed->map(function ($item) {
|
||||
return $item->getRawOriginal();
|
||||
})->sum('filesize');
|
||||
|
||||
return $user_capacity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user full folder tree
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function getFolderTreeAttribute()
|
||||
{
|
||||
return FileManagerFolder::with(['folders.shared', 'shared:token,id,item_id,permission,protected'])
|
||||
->where('parent_id', 0)
|
||||
->where('user_id', $this->id)
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Format avatar to full url
|
||||
*
|
||||
* @return \Illuminate\Contracts\Routing\UrlGenerator|string
|
||||
*/
|
||||
public function getAvatarAttribute()
|
||||
{
|
||||
// Get avatar from external storage
|
||||
if ($this->attributes['avatar'] && is_storage_driver(['s3', 'spaces', 'wasabi', 'backblaze'])) {
|
||||
return Storage::temporaryUrl($this->attributes['avatar'], now()->addDay());
|
||||
}
|
||||
|
||||
// Get avatar from local storage
|
||||
if ($this->attributes['avatar']) {
|
||||
return url('/' . $this->attributes['avatar']);
|
||||
}
|
||||
|
||||
return url('/assets/images/' . 'default-avatar.png');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set user billing info
|
||||
*
|
||||
* @param $billing
|
||||
* @return UserSettings
|
||||
*/
|
||||
public function setBilling($billing)
|
||||
{
|
||||
$this->settings()->update([
|
||||
'billing_address' => $billing['billing_address'],
|
||||
'billing_city' => $billing['billing_city'],
|
||||
'billing_country' => $billing['billing_country'],
|
||||
'billing_name' => $billing['billing_name'],
|
||||
'billing_phone_number' => $billing['billing_phone_number'],
|
||||
'billing_postal_code' => $billing['billing_postal_code'],
|
||||
'billing_state' => $billing['billing_state'],
|
||||
]);
|
||||
|
||||
return $this->settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the password reset notification.
|
||||
*
|
||||
* @param string $token
|
||||
* @return void
|
||||
*/
|
||||
public function sendPasswordResetNotification($token)
|
||||
{
|
||||
$this->notify(new ResetPassword($token));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user favourites folder
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function favourite_folders()
|
||||
{
|
||||
return $this->belongsToMany(FileManagerFolder::class, 'favourite_folder', 'user_id', 'folder_unique_id', 'id', 'unique_id')->with('shared:token,id,item_id,permission,protected');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get 5 latest uploads
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany|\Illuminate\Database\Query\Builder
|
||||
*/
|
||||
public function latest_uploads()
|
||||
{
|
||||
return $this->hasMany(FileManagerFile::class)->with(['parent'])->orderBy('created_at', 'DESC')->take(40);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all user files
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function files()
|
||||
{
|
||||
return $this->hasMany(FileManagerFile::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all user files
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function files_with_trashed()
|
||||
{
|
||||
return $this->hasMany(FileManagerFile::class)->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user attributes
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasOne
|
||||
*/
|
||||
public function settings()
|
||||
{
|
||||
return $this->hasOne(UserSettings::class);
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* App\UserSettings
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $user_id
|
||||
* @property int $storage_capacity
|
||||
* @property string|null $billing_name
|
||||
* @property string|null $billing_address
|
||||
* @property string|null $billing_state
|
||||
* @property string|null $billing_city
|
||||
* @property string|null $billing_postal_code
|
||||
* @property string|null $billing_country
|
||||
* @property string|null $billing_phone_number
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|UserSettings newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|UserSettings newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|UserSettings query()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|UserSettings whereBillingAddress($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|UserSettings whereBillingCity($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|UserSettings whereBillingCountry($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|UserSettings whereBillingName($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|UserSettings whereBillingPhoneNumber($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|UserSettings whereBillingPostalCode($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|UserSettings whereBillingState($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|UserSettings whereId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|UserSettings whereStorageCapacity($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|UserSettings whereUserId($value)
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class UserSettings extends Model
|
||||
{
|
||||
public $timestamps = false;
|
||||
|
||||
protected $guarded = ['id', 'storage_capacity'];
|
||||
}
|
||||
815
changelog.md
Normal file
815
changelog.md
Normal file
@@ -0,0 +1,815 @@
|
||||
## Version 2.2
|
||||
#### Release date: 18. May 2022
|
||||
|
||||
### Fixes
|
||||
- Solved issue with database backup notifications
|
||||
- Solved issue where after team member was invited into team folder, email with urging the recipient to create new account was sent
|
||||
- You are now allowed to set price for metered billing in 3 decimal places
|
||||
- Solved UI issue with empty notification popup
|
||||
- Plans in fixed subscription are now automatically sorted from lower to higher price
|
||||
- When new user was created via admin, the verification email was send
|
||||
- Item name in list view type is now extended on the full page width
|
||||
|
||||
### New Features
|
||||
- API version 1 released
|
||||
- Paginated records loading with infinity scroller
|
||||
- If you send file request for native user via email option, the push notification will be sent to the user
|
||||
- Ability to test your websocket (Broadcasting) connection via Admin / Server / Broadcasting tab
|
||||
|
||||
## Version 2.1.3
|
||||
#### Release date: 10. May 2022
|
||||
- Ability to manually synchronize plans in fixed subscription type
|
||||
- Improved sanitization for .env values to prevent crash your app
|
||||
- Improved reCaptcha validation errors
|
||||
- Fixed issue when upload doesn't start after you drag the file into empty view
|
||||
- Fixed issue when homepage flash to sign in screen after the homepage was disabled in admin panel
|
||||
- Fixed trash navigator issue
|
||||
- Fixed issue when you create plan with 0 team members amount
|
||||
|
||||
## Version 2.1.2
|
||||
#### Release date: 8. May 2022
|
||||
- Fixed issue with chunk uploads (Critical issue affected since 2.1.1)
|
||||
- Fixed issue with creating plan with unlimited team members
|
||||
|
||||
## Version 2.1.1
|
||||
#### Release date: 29. April 2022
|
||||
- Fixed issue with reading image upload
|
||||
|
||||
## Version 2.1.0
|
||||
#### Release date: 25. April 2022
|
||||
- New remote upload function
|
||||
- Broadcast server implementation, for more info check [Broadcasting Guide](https://gist.github.com/MakingCG/a702a112be63bc6f0032dd55522327cf#broadcasting)
|
||||
|
||||
## Version 2.0.19
|
||||
#### Release date: 21. April 2022
|
||||
- Fixed issue with Backblaze credentials set up
|
||||
- The switch button in archived plans is now hidden
|
||||
- updated readme.md
|
||||
- Fixed upload progressbar in mobile version
|
||||
- Added Viet Nam language into the language editor
|
||||
|
||||
## Version 2.0.18
|
||||
#### Release date: 19. April 2022
|
||||
- Fixed issue with Google login button
|
||||
- Fixed issue with PayPal subscription
|
||||
|
||||
## Version 2.0.17
|
||||
#### Release date: 12. April 2022
|
||||
- Added option to use FTP as VueFileManager file storage server
|
||||
|
||||
## Version 2.0.16
|
||||
#### Release date: 8. April 2022
|
||||
- Test mailgun, ses and postmark connection before storing your credentials into the app
|
||||
- UI enhancements & fixes
|
||||
|
||||
## Version 2.0.15
|
||||
#### Release date: 6. April 2022
|
||||
- Wasabi region list updated
|
||||
- The delay after first upload in file request when the interface wasn't showing was removed
|
||||
- If adsense banner location isn't filled, the ads space won't be showed
|
||||
- Fixed issue when in grid view you tried to move image into another folder
|
||||
- Fixed issue when you can't move or delete items via mobile multiselect function
|
||||
- You can now open searched file from spotlight in FilePreview mode to access file settings and functions
|
||||
|
||||
## Version 2.0.14
|
||||
#### Release date: 5. April 2022
|
||||
- Added option to set default max team members for new user registrations
|
||||
- Added new app settings shortcuts findable by spotlight - Application, Login & Registration, Appearance, Adsense, Homepage, Environment, Server
|
||||
- Now in 2fa set up challenge user is required to confirm his app setup with code
|
||||
|
||||
## Version 2.0.13
|
||||
#### Release date: 4. April 2022
|
||||
- Auto plan synchronization improvements.
|
||||
- Fixed issue with thumbnails in grid preview type
|
||||
- PayPal sandbox option was added into PayPal credentials setup
|
||||
- Fixed issue in mobile spotlight where you trying open searched image
|
||||
|
||||
## Version 2.0.12
|
||||
#### Release date: 2. April 2022
|
||||
- Added status column to the fixed plan table
|
||||
- Ability to delete fixed plan if there isn't any subscribed user
|
||||
- Improved error handling in subscription module
|
||||
|
||||
## Version 2.0.11
|
||||
#### Release date: 1. April 2022
|
||||
- Improved email setup in administration settings and setup wizard
|
||||
- Ability to set custom s3 compatible service in administration settings and setup wizard
|
||||
- Test s3 connection before set up in administration settings and setup wizard
|
||||
- Test smtp connection before set up in administration settings and setup wizard
|
||||
|
||||
## Version 2.0.0 - 2.0.10
|
||||
#### Release date: 31. March 2022
|
||||
- You can now generate link for direct download via context menu in copy link input
|
||||
- You can now upgrade from regular to extended license version via admin panel
|
||||
- Fixed issue with .dwg file icon
|
||||
- You can now set uploading chunk file size directly in your admin
|
||||
- Team Folders and Shared With Me root folder has now disabled delete/move function
|
||||
- When you invite someone to your team folder, all his usage (storage, bandwidth) will be on behalf of you, not the member
|
||||
- Fixed issue when you are moving folders between your Team Folders and Private files and vice versa
|
||||
- Fixed issue when downloading bandwidth doesn't write to the user total bandwidth stats
|
||||
- Fixed issue with language strings which indicate limited/unlimited team members in fixed plans
|
||||
- Fixed issue when you are trying delete user registered with only the first name
|
||||
- Fixed issue with Adsense where banners wasn't placed correctly by their described location
|
||||
|
||||
## Version 2.0.0
|
||||
#### Release date: 21. March 2022
|
||||
|
||||
**User Interface**
|
||||
- Fullscreen mode can be set by double arrow icon on top of navigation sidebar in file page or by action in spotlight
|
||||
- In mobile version you can now by opening image or document move seamlessly to another by swipe gesture
|
||||
- Emoji picker was redesigned and now offer better experience to pick your favourite emoji for your folder icon
|
||||
- Actions like create folder, upload files and any others was moved and grouped by 'Frequently used' and 'Others' category under single button
|
||||
- User profile, Dashboard and other admin pages was redesigned
|
||||
- Mac users can now switch between native emojis and twemojis
|
||||
- New button to switch between dark/light mode was added under the main navigation in desktop
|
||||
- Now when you undo in your browser, it goes back to the previous folder
|
||||
|
||||
**Spotlight**
|
||||
- Search through your files and folders
|
||||
- Can be used as quick navigation through your folders or app pages
|
||||
- Ability to search actions like toggle emojis, toggle dark/light mode, creating file request, new user and many more
|
||||
- Search your users by activating user filter with keyboard shortcut (u+space)
|
||||
- Ability to call spotlight with cmd/ctrl + k from any location in app like admin or user profile
|
||||
- Ability from any location in the app to show document, image or video in file preview component
|
||||
- Ability to use keyboard shortcuts to navigate in spotlight like arrow up/down, enter
|
||||
|
||||
**Collaboration**
|
||||
- New Team Folders and Shared with Me categories
|
||||
- Ability to create new team folder and invite users by email invitation, or if user is app user, then push notification will be sent as well.
|
||||
- Ability to convert existing folder into Team Folder and invite members into it.
|
||||
- Ability to dissolve your team folder. All members permissions will be revoked and your folder will be moved into My Files category.
|
||||
- Ability to leave folder if you are member of someone team folder
|
||||
- Received invitation can be accepted or declined
|
||||
- User avatar indicate in file icon who is the owner of the file
|
||||
- New team heads icon in desktop and mobile toolbar to indicate team members in the team folder
|
||||
|
||||
**Metered Billing**
|
||||
- New metered billing where user can be charged by what he uses.
|
||||
- Bandwidth, storage, flat fee and members are optional features which can be charged, not required
|
||||
- Native balance system from which user is charger at the end of current billing period
|
||||
- User can fund his balance by PayPal and Paystack single payment option
|
||||
- If Stripe payment method is allowed, user can register his credit card and all future payments for billing period will be automatically charged. If there is any credit in balance and is sufficient, then this amount will be preferred instead of credit card charging
|
||||
- User has ability to add/delete his payment methods (only Stripe)
|
||||
- Admin has ability to increase user balance with certain amount
|
||||
- Ability to set registration bonus for every new user registration
|
||||
- User can set billing alert with certain amount. When this amount will be reached, the notification will be sent.
|
||||
- New Usage Estimates widget in user profile which provide price estimates for current billing period
|
||||
- New transactions widget in user profile with usage history
|
||||
|
||||
**Fixed Billing**
|
||||
- Plans with yearly billing period is now supported
|
||||
- New subscription widget with subscription details in user profile
|
||||
- New Payment Method widget to manage user credit cards (available only for Stripe)
|
||||
- New popup component to subscribe or upgrade account plan
|
||||
|
||||
**Notification Center**
|
||||
- Ability to see notifications by Unread and Read category
|
||||
- Interactive notifications to seamlessly perform actions from it if needed
|
||||
- If broadcasting is set, notifications will be received just in time and showed in bottom right corner of the app
|
||||
- Ability to clear all notifications by button
|
||||
|
||||
**Zip**
|
||||
- New on the fly zipping system zips files without additional storage usage
|
||||
- User can now select any files with any folders and zip them together
|
||||
|
||||
**Sharing**
|
||||
- Redesigned sharing popup component for better user experience
|
||||
- Shared video file (.mp4) has now ability to play video in shared page
|
||||
- Ability to get share link via QR code
|
||||
- Ability to generate embeddable code with shared item (beta)
|
||||
- App logo was added into single file share pages
|
||||
|
||||
**File Request**
|
||||
- User can generate file request by opening context menu over single folder or call file request from spotlight
|
||||
- Ability to set custom folder name if file request will be filled
|
||||
- Ability to leave a message for guest
|
||||
- Ability to send file request by email for certain email recipient
|
||||
- Full-fledged reach UI for guests to upload and manage their files directly in file request
|
||||
- Push notification about filled file request will be received for user
|
||||
|
||||
**Folder Upload**
|
||||
- Now user can upload their folders. The same folder structure will be recreated in the app
|
||||
|
||||
**User Settings**
|
||||
- New appearance option was added where user can set his theme mode by dark, light or based by system option
|
||||
- New default emoji option was added where Apple user can switch between native emojis or twemoji
|
||||
- 2fa setup challenge option was added. User can store and generate backup keys.
|
||||
- New Personal Access Token section was added where user can generate access token for API requests.
|
||||
- New 'Current Password' input was added into change password functionality
|
||||
- New widget to track the latest upload and download was added into the Storage tab
|
||||
- Storage usage widget was redesigned
|
||||
- New Billing tab with all subscription related items was added
|
||||
|
||||
**Login & Registration**
|
||||
- Email confirmation for new account registrations can be required
|
||||
- Integrated database with more than 550 disposable temporary email services to automatically deny new account registrations
|
||||
- Users can now set up 2 factor verification with their favourite authenticator app
|
||||
- reCaptcha was added to provide security for your registration and contact form
|
||||
- Social authentication was implemented with Facebook, Google and GitHub drivers.
|
||||
|
||||
**Adsense**
|
||||
- Adsense will be integrated into VueFileManager
|
||||
- The ads are showing in 3 locations - File Viewport, Download Page and Homepage
|
||||
|
||||
**Setup Wizard**
|
||||
- Server check before you running installation, it will show you if you had set up your server correctly
|
||||
- Dark mode support
|
||||
- Now you don't need to set up your subscription system in setup wizard
|
||||
|
||||
**Broadcasting**
|
||||
- Pusher implementation for live communication
|
||||
- Native websocket server as replacement for Pusher (more details soon)
|
||||
- Live notification
|
||||
|
||||
**System**
|
||||
- Database backups on daily basis
|
||||
- After you upload image, additionals thumbnails will be generated to provide you faster browsign experience through your image gallery
|
||||
|
||||
**Admin & Settings**
|
||||
|
||||
**Dashboard**
|
||||
- New widget to track the latest upload and download was added
|
||||
- New widget with the latest transactions was added into extended license version
|
||||
- New earnings widget was added
|
||||
- New alerts will tell you if you are missing plan or you don't have running cron correctly
|
||||
|
||||
**Settings / Server**
|
||||
- Ability to see if cron job is running correctly
|
||||
- Ability to download your server log from admin panel
|
||||
- Ability to see latest 5 database backups
|
||||
- Ability to check if writable permission for exact folders are set correctly
|
||||
- Ability to check if you have correctly set php version and php.ini variables
|
||||
- Ability to see if you have installed all required php extensions
|
||||
|
||||
**Settings / Environment**
|
||||
- Ability to set Broadcasting from admin settings
|
||||
- Ability to set Storage Driver from admin settings
|
||||
- Ability to set Mail Driver from admin settings
|
||||
|
||||
**Settings / Appearance**
|
||||
- Ability to change entire VueFileManager color scheme
|
||||
- Ability to set dark mode logo for main and horizontal logo
|
||||
- Ability to set your own OG Image
|
||||
- Ability to set your own Touch Image
|
||||
|
||||
**Settings / Login & Registration**
|
||||
- New option where you can require email verification was added
|
||||
- New widgets to set up Facebook, Google and GitHub social authentication
|
||||
|
||||
**Settings / Application**
|
||||
- New options to set up reCaptcha
|
||||
|
||||
**Settings / Adsense**
|
||||
- Ability to manage Google Adsense
|
||||
|
||||
**Dev**
|
||||
- PHP 8 support
|
||||
- New DDD design for the backend
|
||||
- Shipped with the latest version of Laravel 9.x
|
||||
- Passport was replaced by Sanctum
|
||||
- New artisan command that expressly installs the entire application
|
||||
- New artisan command that expressly installs the entire application with the demo data
|
||||
- ~80% Of the frontend code was migrated into Tailwind v3. We will continue to reach 100% tailwind friendly
|
||||
|
||||
|
||||
## Version 1.8.3.13
|
||||
#### Release date: 9. December 2021
|
||||
- Fixed issue when visitor can't download files from shared folder with 'Can only view and download' privilege
|
||||
- Fixed issue with sending contact form
|
||||
|
||||
## Version 1.8.3.11-12
|
||||
#### Release date: 7. July 2021
|
||||
- Fixed issue when you tried load folders/files with special characters name
|
||||
|
||||
## Version 1.8.3.10
|
||||
#### Release date: 29. June 2021
|
||||
- Security patch (Critical severity)
|
||||
|
||||
## Version 1.8.3.9
|
||||
#### Release date: 18. June 2021
|
||||
|
||||
**Fixes:**
|
||||
- Fixed issue when in some cases your server can suffer with increasing RAM usage
|
||||
- Fixed translation issue in some user mobile pages
|
||||
- Mobile navigation fix with hidden back button
|
||||
- Fixed issue where in some case special characters was excerpted from uploaded filename
|
||||
|
||||
## Version 1.8.3.8
|
||||
#### Release date: 15. June 2021
|
||||
- Alibaba Cloud OSS support
|
||||
|
||||
## Version 1.8.3.7
|
||||
#### Release date: 9. June 2021
|
||||
- App name fix in email templates
|
||||
|
||||
## Version 1.8.3.6
|
||||
#### Release date: 7. June 2021
|
||||
- Translation improvements on backend
|
||||
|
||||
## Version 1.8.3.5
|
||||
#### Release date: 24. May 2021
|
||||
- Translation improvements on backend
|
||||
|
||||
## Version 1.8.3.4
|
||||
#### Release date: 15. May 2021
|
||||
- Upload progressbar fix
|
||||
|
||||
## Version 1.8.3.3
|
||||
#### Release date: 10. May 2021
|
||||
- Security update (upgrade required)
|
||||
|
||||
## Version 1.8.3.2
|
||||
#### Release date: 17. April 2021
|
||||
|
||||
**Fixes:**
|
||||
- Fixed multi select on desktop browser
|
||||
|
||||
## Version 1.8.3.1
|
||||
#### Release date: 18. April 2021
|
||||
|
||||
**Fixes:**
|
||||
- Fixed previewing files in mobile devices
|
||||
|
||||
## Version 1.8.3
|
||||
#### Release date: 17. April 2021
|
||||
|
||||
**Features:**
|
||||
- Ability to create new language
|
||||
- Ability to set default language for aplication
|
||||
- Ability to show pdf files in VueFileManager
|
||||
|
||||
|
||||
## Version 1.8.2.3
|
||||
#### Release date: 21. March 2021
|
||||
|
||||
**Fixes:**
|
||||
- Fixed not found page
|
||||
- Fixed admin menu in regular license
|
||||
|
||||
|
||||
## Version 1.8.2.2
|
||||
#### Release date: 12. March 2021
|
||||
|
||||
**Fixes:**
|
||||
- Fixed file preview in single shared file wasn't showing correctly
|
||||
|
||||
|
||||
## Version 1.8.2.1
|
||||
#### Release date: 25. February 2021
|
||||
|
||||
**Fixes:**
|
||||
- Fixed jumping upload progressbar
|
||||
|
||||
## Version 1.8.2
|
||||
#### Release date: 20. February 2021
|
||||
|
||||
**Folders:**
|
||||
- Ability to change folder icon as Emoji
|
||||
- Ability to change folder icon color from 22 colors set
|
||||
|
||||
**Fixes:**
|
||||
- Added zip folder into mobile folder menu
|
||||
- Removed Autofocus in mobile creating folder
|
||||
|
||||
## Version 1.8.1
|
||||
#### Release date: 7. February 2021
|
||||
|
||||
**Functions:**
|
||||
- Ability to zip and download folder with content within
|
||||
- Ability to send shared folder/file to multiple email recipients
|
||||
- Ability to send share link in existing shared items
|
||||
- Every user has ability to change his timezone in profile settings
|
||||
|
||||
**UI & UX:**
|
||||
- After click on logout if your request is long, you will see processing window
|
||||
- Move/Share/Delete icons is unactive when you don't have selected file in desktop version
|
||||
- Move/Share/Delete icons is hidden in touchable devices
|
||||
- Delete item in contextmenu is now highlighted as red
|
||||
- Hidden scroller in navigation panel on windows
|
||||
- Delete icon for clear text field in rename popup
|
||||
- After opening video, it's start playing automatically
|
||||
- Autofocus and selecting folder name after creating it in desktop version
|
||||
|
||||
**Fixes:**
|
||||
- Max Upload frontend validation fix
|
||||
- In latest uploads files are sorted alwas from newest
|
||||
- Download icon in image/video preview on mobile device and shared folder with read/download privilegies
|
||||
|
||||
**Regular License:**
|
||||
- Included landing page
|
||||
- Included Privacy Policy, Terms of Condition and Cookies policy pages
|
||||
- Included contact form page
|
||||
|
||||
## Version 1.8
|
||||
#### Release date: 21. December 2020
|
||||
|
||||
**User Interface:**
|
||||
|
||||
- Added navigator to shared page with folders when you have multiple folders within for better user experience
|
||||
- New popup to rename your item in desktop & mobile version
|
||||
- Trash moved to Home page under 'Recent Uploads' navigation item
|
||||
- Ability to collapse navigator or favourites widget in File page
|
||||
- Ability to remove uploaded logo and get back to text logo
|
||||
- Ability to cancel uploading via x button
|
||||
- Prevent browser 'Go Back' when you undesirably trying to go to previous page after sign in to your account
|
||||
|
||||
**Sorting**
|
||||
|
||||
- New sorting menu in desktop version buttons panel with multiple actions
|
||||
- New view button with sorting options in mobile version
|
||||
- Ability to sort files & folders in date or alphabetical order
|
||||
|
||||
**Bulk Operations**
|
||||
|
||||
- Select multiple items in desktop version by holding shift key or ctrl/cmd key for increase or decrease selection
|
||||
- New multi select mode in mobile version activated by clicking on 'Select' button below search bar
|
||||
- Ability to select all or deselect all items in mobile version of multi select
|
||||
- Select multiple items and delete them by delete/backspace key
|
||||
- Select multiple items and move them by drag&drop to another folder in view or move them via move option
|
||||
- Ability to move multiple item by dragging them to folder in navigator panel
|
||||
- Ability to set multiple favourite folders by dragging them to favourites group in sidebar panel
|
||||
- Ability to cancel multiple shareing items in 'My Sharing Items' sections via context menu action
|
||||
- New compact UI component for indicate dragging action
|
||||
- Ability to download multiple files from selection as zip
|
||||
- New scrollbar for the Windows users
|
||||
|
||||
**Bug Fixes:**
|
||||
|
||||
- Title name of favourite folder overflowed sidebar when you have long title
|
||||
- Share button in image preview appear when you are in shared public folder
|
||||
- Fixed search indexer overload in high traffic demands scenario
|
||||
- Folder tree in navigator now has correct ordering with folder list in file view
|
||||
|
||||
## Version 1.7.12
|
||||
#### Release date: 16. November 2020
|
||||
|
||||
- Limit maximum upload size on single file
|
||||
|
||||
## Version 1.7.11
|
||||
#### Release date: 24. October 2020
|
||||
|
||||
- Reading exif data and showing them in file info panel
|
||||
- Ability to ban mimetypes. You can find blacklist setup in Settings / Application
|
||||
- Lazy loading for images. If you have hundreds of images in your folder, you will have experience with seamlessly loading.
|
||||
- Fixed bug with context menu overflow in shared page
|
||||
- Fixed button overflow on small mobile screens in popups.
|
||||
|
||||
## Version 1.7.10
|
||||
#### Release date: 31. August 2020
|
||||
|
||||
- Ability to see file in full preview (images, videos[mp4, web, ogv], audios)
|
||||
|
||||
## Version 1.7.9
|
||||
#### Release date: 26. August 2020
|
||||
|
||||
- Ability to set expiration for shared link
|
||||
- If user is logged in, after visit SignIn page will be redirected to files page
|
||||
|
||||
## Version 1.7.8
|
||||
#### Release date: 25. August 2020
|
||||
|
||||
- Ability to read file metadata in shared link for instant messengers
|
||||
|
||||
## Version 1.7.7
|
||||
#### Release date: 24. August 2020
|
||||
|
||||
- Backend pagination for native data
|
||||
- Added clear cache button to app settings
|
||||
- Removed deprecated commands
|
||||
- Code splitting support for Vue router
|
||||
- Added region list to setup wizard
|
||||
- added htaccess to redirect domain root to /public folder
|
||||
- Fixed issue with non VueFileManager created Stripe plans
|
||||
- Fixed email setup in app settings
|
||||
- Additional text logo fix in Sign pages
|
||||
|
||||
## Version 1.7.6
|
||||
#### Release date: 19. August 2020
|
||||
|
||||
- Folder delete fix
|
||||
|
||||
## Version 1.7.5
|
||||
#### Release date: 10. August 2020
|
||||
- Bug fixes and UX enhancement
|
||||
|
||||
|
||||
## Version 1.7.4
|
||||
#### Release date: 5. August 2020
|
||||
- Bug fixes and UX enhancement
|
||||
|
||||
|
||||
## Version 1.7.3
|
||||
#### Release date: 30. July 2020
|
||||
|
||||
- Chunk Upload
|
||||
- Multipart upload support on external storages (Ability to upload bigger files)
|
||||
- Progressbar now show upload in %
|
||||
|
||||
## Version 1.7.2
|
||||
#### Release date: 22. July 2020
|
||||
|
||||
- Readme update
|
||||
- Improvement on Setup Wizard
|
||||
|
||||
## Version 1.7.1
|
||||
#### Release date: 21. July 2020
|
||||
|
||||
- Fixed register button in Regular license
|
||||
|
||||
## Version 1.7
|
||||
#### Release date: 20. July 2020
|
||||
|
||||
**Software as a Service**
|
||||
|
||||
- Ability to create monthly subscription plans with storage space
|
||||
- Ability to charge customers for storage space with Stripe payment service
|
||||
- List all of your customer invoices
|
||||
- Included Legal pages (Terms of Service, Privacy Policy, Cookie Policy)
|
||||
- Included Cookie disclaimer in SaaS version
|
||||
- Landing page for present your service solution
|
||||
|
||||
**Settings - Application**
|
||||
|
||||
- Storage limitation option
|
||||
- Default storage space for new accounts option
|
||||
- Allow user registration option
|
||||
- Set your contact email for message form in landing page
|
||||
- Set your google analytics code to track visitors
|
||||
|
||||
**Settings - Appearance**
|
||||
|
||||
- App title option
|
||||
- App description option
|
||||
- Change your logo and favicon option
|
||||
|
||||
**Settings - Billing**
|
||||
|
||||
- Set your company name and VAT number options in SaaS version
|
||||
- Set your billing country adress. options in SaaS version
|
||||
|
||||
**Settings - Payments**
|
||||
|
||||
- Allow subscription payments option
|
||||
- Get your stripe webhook link option
|
||||
|
||||
**Settings - Homepage**
|
||||
|
||||
- Ability to change content, show/hide sections for Landing page presentation
|
||||
|
||||
**Settings - Email**
|
||||
|
||||
- Ability to set your email credentials from admin panel
|
||||
|
||||
**Admin - Users**
|
||||
|
||||
- Subscription plan details
|
||||
- List of all user invoices
|
||||
|
||||
**Dashboard**
|
||||
|
||||
- Showed widget with your total users
|
||||
- Showed widget with total space usage
|
||||
- Showed widget with total premium users
|
||||
- Showed widget with latest registrations
|
||||
- Showed latest VueFileManager version
|
||||
- Showed license type (Extend/Regular)
|
||||
|
||||
**User**
|
||||
|
||||
- Added billing information to profile settings in Saas Version
|
||||
- Added subscription plan page to get information about current subscription. Ability to cancel or renew subscription
|
||||
- Added payment card page with ability to list all registered card, add new credit card, remove card or set selected card as default payment.
|
||||
- Added invoices page where are listed all invoices
|
||||
- Added invoice page detail with ability to print invoice with
|
||||
|
||||
**VueFileManager design**
|
||||
|
||||
- Circle notice icon in avatar in case of incomplete payment or required action to upgrade storage capacity
|
||||
|
||||
**Setup Wizard**
|
||||
|
||||
- The UI for Install and configure your VueFIlemanager
|
||||
- Purchase code verification
|
||||
- Database credentials setup
|
||||
- Ability to setup Stripe for Extended License (Set Credentials, set billing informations and create subscription plans)
|
||||
- Storage Setup
|
||||
- Email credentials setup
|
||||
- General settings setup
|
||||
- Admin setup
|
||||
|
||||
**Storage**
|
||||
|
||||
- Added support for Object Cloud Storage by Wasabi
|
||||
- Added support for Backblaze B2 Cloud Storage
|
||||
Fixes
|
||||
- Fixed issue when you move parent directory to it’s children directory, then your folder disappear.
|
||||
- Fixed issue which appear on specifical hosting configuration when you can’t load shared folder content.
|
||||
|
||||
**Others**
|
||||
|
||||
- Improved form design
|
||||
- Profile settings get sidebar panel navigation
|
||||
- Improved design for important notices
|
||||
- Updated i18n language files
|
||||
- Added agreement in registration page for SaaS version
|
||||
- Upgraded laravel framework from 6 to 7 version
|
||||
|
||||
**Upgrading**
|
||||
|
||||
- All upgrading backend operations is running on background after putting new source code to app directory (Don't forget create backup of your database and storage before make any changes in your production application)
|
||||
- UI page for additional options when it’s neccesarily
|
||||
- Upgrading To 1.7 From 1.6.x or newest
|
||||
|
||||
## Version 1.6.4
|
||||
#### Release date: 9. June 2020
|
||||
|
||||
- Fileview xscroller fix
|
||||
|
||||
## Version 1.6.3
|
||||
#### Release date: 5. June 2020
|
||||
|
||||
- Fixed svg upload
|
||||
- Fixed scrolling in main file view
|
||||
|
||||
## Version 1.6.2
|
||||
#### Release date: 31. May 2020
|
||||
|
||||
- Fixed popups on mobile version
|
||||
|
||||
## Version 1.6.1
|
||||
#### Release date: 31. May 2020
|
||||
|
||||
- Fixed npm building crash on web server
|
||||
|
||||
## Version 1.6
|
||||
#### Release date: 28. May 2020
|
||||
|
||||
**User Management**
|
||||
|
||||
- List of all registered users
|
||||
- Ability to create new user
|
||||
- Change user role (Admin or User)
|
||||
- Change user storage capacity in GBs
|
||||
- User storage capacity usage preview
|
||||
- Send email to user for password reset
|
||||
- Ability to delete user with all user data and stored files
|
||||
Others
|
||||
- Redesigned User profile settings
|
||||
- Small bug fixes
|
||||
- New artisan command for upgrade app (for more info check upgrade guide)
|
||||
- Upgrading To 1.6 From 1.4.2 or newest
|
||||
|
||||
## Version 1.5.2
|
||||
#### Release date: 22. May 2020
|
||||
|
||||
- Empty page fix
|
||||
- Log out in mobile fix
|
||||
- Dark mode fixes
|
||||
- Password reset bug fixes
|
||||
|
||||
## Version 1.5
|
||||
#### Release date: 19. May 2020
|
||||
|
||||
**UI & UX**
|
||||
|
||||
- New navigation menu with Home, Shared, Trash, Settings locations in desktop
|
||||
- New dynamic sidebar with folder tree navigation, file categories and tools
|
||||
- Folder tree navigator in main file page
|
||||
- Added Participant uploads category to shared page
|
||||
- Added recent uploads category to file page
|
||||
- New settings page with separated Profile, Password and Storage
|
||||
- Updated colors for dark mode
|
||||
- Improvement desgin across all components
|
||||
- Added (X) close button to all popups
|
||||
- Added editing icons (move, share) to main bar
|
||||
- More transparent context menus with action groups
|
||||
Mobile
|
||||
- New main navigation menu
|
||||
- Added item thumbnails to mobile contextmenu
|
||||
Others
|
||||
- Public shared image now open in an original image page
|
||||
- New page with storage usage details
|
||||
|
||||
## Version 1.4.2
|
||||
#### Release date: 6. May 2020
|
||||
|
||||
**External Storage Services**
|
||||
|
||||
- Amazon Web Services S3 support
|
||||
- Digital Ocean Spaces support
|
||||
- Updated documentation
|
||||
- New blog with some handy tips and news about VueFileManager
|
||||
|
||||
## Version 1.4.1
|
||||
#### Release date: 4. May 2020
|
||||
|
||||
**Translations**
|
||||
|
||||
- Added Chinese (Simplified) language (thanks haimang to contribute)
|
||||
Bugs
|
||||
- Go to profile in mobile version
|
||||
- Internal front-end bug
|
||||
Error logs
|
||||
- Added when passport client isn’t set up correctly
|
||||
- Added when database connection isn’t available
|
||||
|
||||
**Others**
|
||||
|
||||
- Updated terminal info when you are running php artisan setup:prod
|
||||
- Updated documentation with more describing installation process
|
||||
|
||||
## Version 1.4
|
||||
#### Release date: 1. May 2020
|
||||
|
||||
**Sharing**
|
||||
|
||||
- Share your folders and files
|
||||
- Added sidebar group with shared items
|
||||
- Added UI icons to item preview to look which item is shared and which item was uploaded by participant
|
||||
|
||||
**Folders**
|
||||
|
||||
- User can share folder content
|
||||
- User can protect folder content by password
|
||||
- User can set permission to interact with shared folder - only view and download or view, download, upload, rename, delete and move items
|
||||
|
||||
**Files**
|
||||
|
||||
- User can share single file
|
||||
- User can protect single file by password
|
||||
|
||||
**Others**
|
||||
|
||||
- Small UI improvements
|
||||
- Bug fixes
|
||||
- Upgrading to 1.4 from 1.3.x
|
||||
|
||||
## Version 1.3.1
|
||||
#### Release date: 8. April 2020
|
||||
|
||||
- Bug fixes
|
||||
- Upgrading to 1.3.1 from 1.2
|
||||
|
||||
## Version 1.3
|
||||
#### Release date: 3. April 2020
|
||||
|
||||
- i18n localization support
|
||||
- Added SK, EN language files
|
||||
- Video/Audio preview in file preview panel (Thanks to Joshua Fouyon to participating on this feature)
|
||||
- Drop uploading (You can now drag files from desktop and drop it to VueFileManager)
|
||||
- Fixed bug when rename item in safari browser
|
||||
- Fixed bug when you drag folder from trash to favourites in sidebar panel
|
||||
- small functions and design improvements
|
||||
- Upgrading to 1.3 from 1.2
|
||||
|
||||
## Version 1.2
|
||||
#### Release date: 29. March 2020
|
||||
|
||||
- Move your items by folder tree
|
||||
- Fixed bug with image rotation on iOS Device
|
||||
- Improved animations
|
||||
- Small design changes
|
||||
- iOS web app capable support
|
||||
|
||||
## Version 1.1.1
|
||||
#### Release date: 17. March 2020
|
||||
|
||||
- Bug fixes
|
||||
|
||||
## Version 1.1
|
||||
#### Release date: 15. March 2020
|
||||
|
||||
**User Authentication**
|
||||
|
||||
- Login to user account
|
||||
- Register new user account
|
||||
- Reset user password
|
||||
|
||||
**Functionality**
|
||||
|
||||
- Added locations to menu
|
||||
- Added trash for deleted folders & files
|
||||
- Restore files or folders from trash
|
||||
- Empty trash function
|
||||
- Favourites folders
|
||||
- List of 5 latest uploads
|
||||
- Profile settings page
|
||||
- Storage info and upload limits
|
||||
|
||||
**Design**
|
||||
|
||||
- Night Mode
|
||||
- Navigation sidebar
|
||||
- Quick action buttons in mobile version
|
||||
- Improved mobile UX
|
||||
- Other small design improvements
|
||||
|
||||
**Settings**
|
||||
|
||||
- Enable/Disable user account registration
|
||||
- Set storage limitation
|
||||
- Set storage capacity for all users
|
||||
|
||||
## Version 1
|
||||
#### Release date: 25. February 2020
|
||||
- Official release
|
||||
313
codecanyon.html
Normal file
313
codecanyon.html
Normal file
@@ -0,0 +1,313 @@
|
||||
<h3>VueFileManager Mobile Browser Screenshots</h3>
|
||||
<img src="https://i.ibb.co/g3r3H49/mobile-files.jpg" alt="Files">
|
||||
<img src="https://i.ibb.co/4Mb7dCN/mobile-teams.jpg" alt="Teams">
|
||||
<img src="https://i.ibb.co/MCB5wjY/mobile-file-popups.jpg" alt="Popups">
|
||||
<img src="https://i.ibb.co/NCQ5RKL/mobile-user-profile.jpg" alt="User Profile">
|
||||
<img src="https://i.ibb.co/8PSJt51/mobile-administration-panel.jpg" alt="App Settings">
|
||||
<img src="https://i.ibb.co/d5kY6cs/mobile-spotlight.jpg" alt="Spotlight">
|
||||
|
||||
<h3>Core Functionalities</h3>
|
||||
<h5><strong>Meticulously Designed User Interface & User Experience</strong></h5>
|
||||
<p>
|
||||
In last 2 years of VueFileManager evolution with help of our users, we spend a lot of time designing gorgeous
|
||||
looking user interface and seamless user experience with our file management frontend. We advocate simplicity and
|
||||
usability.
|
||||
</p>
|
||||
|
||||
<h5><strong>Responsive</strong></h5>
|
||||
<p>
|
||||
Meticulously optimized mobile version of VueFileManager, we just love how nice and easy are all components working.
|
||||
Mobile responsive version should be nice and usable as his bigger desktop brother.
|
||||
</p>
|
||||
|
||||
<h5><strong>Metered Billing System - SaaS (Extended License Required)</strong></h5>
|
||||
<p>
|
||||
Metered billing works like ‘Pay as You Go’. You can charge your users by their usage, how many Gigabytes of data
|
||||
they have stored, how many Gigabytes of data they transfer or just you can set up your fixed flat fee.
|
||||
</p>
|
||||
|
||||
<h5><strong>Offline Payments - SaaS (Extended License Required)</strong></h5>
|
||||
<p>
|
||||
With a metered billing system, users don't need to own and have registered credit cards. VueFileManager has its own
|
||||
credit system where users can increase deposit with a single-payment charge. This charge can be processed By PayPal,
|
||||
Stripe or Paystack provided payment methods - for example Apple Pay, Google Pay, Bank Account, USSD, Mobile Money,
|
||||
EFT, QR Code, PayPal credit and many more.
|
||||
</p>
|
||||
<p>
|
||||
Also, you as an admin can give a bonus in a certain value for every new registration, or send an existing bonus for
|
||||
a user in a certain value. Users with a metered billing system can set their Billing alert with a certain value. All
|
||||
metered subscriptions are settled every 30 days.
|
||||
</p>
|
||||
<p>With Stripe enabled, users can register their credit to charge any payments automatically.</p>
|
||||
|
||||
<h5><strong>Fixed Billing System - SaaS (Extended License Required)</strong></h5>
|
||||
<p>
|
||||
With fixed billing you can set your billing plans in monthly or yearly periods. You can set a limit for max storage
|
||||
disk size or max number of team members.
|
||||
</p>
|
||||
|
||||
<h5><strong>No-SaaS in Default</strong></h5>
|
||||
<p>
|
||||
If you don’t want to run your business with a storage cloud but just using VueFileManager as your own file storage
|
||||
client, you can use the app without all billing functions as well. See our basic demo without subscription module.
|
||||
</p>
|
||||
|
||||
<h5><strong>Upload Files</strong></h5>
|
||||
<p>
|
||||
With VueFileManager you can upload files up to tens of gigabytes, don’t worry that your big files won't be uploaded.
|
||||
We support chunk upload and multipart uploads for your s3 storage service. All work seamlessly.
|
||||
</p>
|
||||
|
||||
<h5><strong>Folder Upload</strong></h5>
|
||||
<p>
|
||||
For VueFileManager it isn't any problem to upload a folder with your files. The same folder structure will be
|
||||
recreated in the app.
|
||||
</p>
|
||||
|
||||
<h5><strong>Sharing Files</strong></h5>
|
||||
<p>
|
||||
With our reach sharing functionalities, you can easily just click on your file or folder, and generate a shared link
|
||||
for everyone. Also you can protect your shared files with your password.
|
||||
</p>
|
||||
<p>
|
||||
Use expiration functionality to automatically expire links, share links directly via email or generate QR code and
|
||||
share it with guys on your left.
|
||||
</p>
|
||||
|
||||
<h5><strong>Shared Pages</strong></h5>
|
||||
<p>
|
||||
If you share any folder with files within, the user has the same user experience as a logged user. He can create
|
||||
folders, name it, upload files or move them into other folders directly in your shared folder.
|
||||
</p>
|
||||
<p>
|
||||
Videos have their own dedicated shared page with your app logo and ability to play video directly in this page with
|
||||
the download button above, try it, it’s magic!
|
||||
</p>
|
||||
|
||||
<h5><strong>File Request</strong></h5>
|
||||
<p>
|
||||
Do you need a lot of files? Just generate a file request, and send your link for this person. The person can use it
|
||||
to upload files directly into your folder or into your home section for files. The user who’s uploading files has
|
||||
the same user experience as the internal account.
|
||||
</p>
|
||||
|
||||
<h5><strong>Teams</strong></h5>
|
||||
<p>
|
||||
Invite your colleagues or family into your team folders, set their permissions and collaborate together seamlessly.
|
||||
</p>
|
||||
|
||||
<h5><strong>Spotlight</strong></h5>
|
||||
<p>
|
||||
With the spotlight, you can search for your users, files, folders, navigate throughout the app, toggle dark mode,
|
||||
toggle emojis and many more from any location in the app. It’s like magic. Good suit for super users.
|
||||
</p>
|
||||
|
||||
<h5><strong>Notification Center</strong></h5>
|
||||
<p>
|
||||
All important events that occur in your account will be recorded in your notifications center. For example, a new
|
||||
team invite, file request was filled, bonus received, billing alert was reached and many more.
|
||||
</p>
|
||||
|
||||
<h5><strong>External Storage Services</strong></h5>
|
||||
<p>
|
||||
You can use it as main storage for all your files external storage service. We support all S3 compatible services
|
||||
like Amazon Web Services S3, Spaces from Digital Ocean, Backblaze, Wasabi, Alibaba Cloud OSS, Storj and many more.
|
||||
</p>
|
||||
|
||||
<h5><strong>Decentralized Storage Service</strong></h5>
|
||||
<p>
|
||||
With Storj DCS (Decentralized Cloud Storage) files aren’t stored in centralized data centers — instead, they're
|
||||
encrypted, split into pieces, and distributed on a global cloud network.
|
||||
</p>
|
||||
|
||||
<h5><strong>Full-Fledged API</strong></h5>
|
||||
<p>
|
||||
You can integrate VueFileManager into your app seamlessly. Users can generate authentication tokens in their profile
|
||||
settings. Documentation for API coming soon.
|
||||
</p>
|
||||
|
||||
<h5><strong>2-Factor Verification</strong></h5>
|
||||
<p>
|
||||
Another layer of security to make sure your files are secured. Users can set up 2 factor verification with their
|
||||
favourite authenticator app.
|
||||
</p>
|
||||
|
||||
<h5><strong>Social Logins</strong></h5>
|
||||
<p>
|
||||
Log into your app with your social account. Currently we support Facebook, Github and Google providers. More is
|
||||
coming soon.
|
||||
</p>
|
||||
|
||||
<h5><strong>Customizable Folder Icons</strong></h5>
|
||||
<p>
|
||||
Set your favourite emoji to your folder as an icon and make VueFileManager more personal for you! If you are an
|
||||
apple user, you can switch between Apple emojis and Tweemojis from twitter.
|
||||
</p>
|
||||
|
||||
<h5><strong>Admin Panel</strong></h5>
|
||||
<p>
|
||||
As admin, you have full control over the entire app, you can create or delete users, manage their storage size, disable registration, require email verification, set upload limits and many more.
|
||||
</p>
|
||||
|
||||
<h5><strong>Dark Mode</strong></h5>
|
||||
<p>
|
||||
We support dark mode natively. Users can set dark mode via application, or let Dark/Light mode handle with preferred
|
||||
OS settings.
|
||||
</p>
|
||||
|
||||
<h5><strong>Language Editor</strong></h5>
|
||||
<p>
|
||||
With our language editor you can translate applications into your home language. It’s at your hand in the admin
|
||||
panel.
|
||||
</p>
|
||||
|
||||
<h5><strong>Auto Database Backup</strong></h5>
|
||||
<p>
|
||||
VueFileManager will take care of your daily database backups. When an unexpected event occurs, your database backup
|
||||
will be ready for you.
|
||||
</p>
|
||||
|
||||
<h5><strong>reCaptcha</strong></h5>
|
||||
<p>
|
||||
reCaptcha will provide security for registration and contact form from internet bots and prevent spammers from
|
||||
abusing your application.
|
||||
</p>
|
||||
|
||||
<h5><strong>Blacklist with more than 550+ Temporary Email Services</strong></h5>
|
||||
<p>
|
||||
We integrated a database with more than 550 disposable temporary email services to deny new account registrations
|
||||
with abusive behavior.
|
||||
</p>
|
||||
|
||||
<h5><strong>AdSense</strong></h5>
|
||||
<p>
|
||||
Monetize your file cloud with Google Adsense service. We natively implement 3 ad slots into the VueFileManager
|
||||
frontend.
|
||||
</p>
|
||||
|
||||
<h5><strong>Server Status</strong></h5>
|
||||
<p>
|
||||
You can check the admin panel server status. You can download your server logs for support communication, check your
|
||||
latest database backups, check if your cron is running smoothly or if you have correctly set up your PHP with all
|
||||
required php extensions.
|
||||
</p>
|
||||
|
||||
<h5><strong>Easy Installation with Setup Wizard</strong></h5>
|
||||
<p>
|
||||
Setup Wizard is a convenient way to set up and configure your VueFileManager app in a few steps. Before you run your
|
||||
installation, Setup Wizard will check all your server components and let you know, when you are missing something.
|
||||
</p>
|
||||
|
||||
<h5><strong>Drag & Drop</strong></h5>
|
||||
<p>You can drag your files or folder to another folder seamlessly</p>
|
||||
|
||||
<h5><strong>Source Code</strong></h5>
|
||||
<p>
|
||||
All source files of VueFileManager are included in download. You can easily inspect code and build your own
|
||||
functionality.
|
||||
</p>
|
||||
|
||||
<h3>Technologies</h3>
|
||||
<ul>
|
||||
<li>Laravel 9.x</li>
|
||||
<li>Vue 2.6.x</li>
|
||||
<li>Tailwind 3</li>
|
||||
</ul>
|
||||
|
||||
<h3>Server Requirements</h3>
|
||||
<ul>
|
||||
<li>PHP >= 8.0.2 version (8.1+ recommended)</li>
|
||||
<li>MySQL 5.6+</li>
|
||||
<li>Nginx or Apache</li>
|
||||
</ul>
|
||||
|
||||
<h3>Useful Links</h3>
|
||||
<p>
|
||||
<a href="https://gist.github.com/MakingCG/a702a112be63bc6f0032dd55522327cf">
|
||||
<strong>Installation Guide</strong>
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://gist.github.com/MakingCG/9c07f8af392081ae5d5290d920a79b5d">
|
||||
<strong>Changelog</strong>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<h3>Tips</h3>
|
||||
<p>
|
||||
<a
|
||||
href="https://medium.com/vuefilemanager/how-to-set-up-vuefilemanager-laravel-application-on-vps-with-debian-10-64676a3ff4d7"
|
||||
>
|
||||
<strong>How to install VueFileManager on VPS with Debian 10</strong>
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
<a
|
||||
href="https://medium.com/vuefilemanager/how-to-set-up-vuefilemanager-with-aws-s3-as-an-external-storage-a2c525aec698"
|
||||
>
|
||||
<strong>How to Set Up AWS S3</strong>
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
<a
|
||||
href="https://medium.com/vuefilemanager/how-to-set-up-vuefilemanager-with-digital-ocean-spaces-as-a-external-storage-6cccf590c23d"
|
||||
>
|
||||
<strong>How to Set Up Digital Ocean Spaces</strong>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<h3>Demos</h3>
|
||||
|
||||
<h5>
|
||||
<strong>
|
||||
<a href="https://demo-metered.vuefilemanager.com/sign-in"> Metered Billing </a>
|
||||
</strong>
|
||||
</h5>
|
||||
<p>
|
||||
Browse demo with the Pay as You Go model. You can try credit system, fund your account balance and see how usage
|
||||
estimates works. Some functions for default howdy account are restricted. Feel free to create your own account with
|
||||
1 GB upload limit.
|
||||
</p>
|
||||
|
||||
<h5>
|
||||
<strong>
|
||||
<a href="https://demo-fixed.vuefilemanager.com/sign-in"> Fixed Billing </a>
|
||||
</strong>
|
||||
</h5>
|
||||
<p>
|
||||
Browse demo with the Fixed model. You can try subscribe to any billing plan available in the app. Some functions for
|
||||
default howdy account are restricted. Feel free to create your own account with 1 GB upload limit.
|
||||
</p>
|
||||
|
||||
<h5>
|
||||
<strong>
|
||||
<a href="https://demo-regular.vuefilemanager.com/sign-in"> Regular without Subscription Module </a>
|
||||
</strong>
|
||||
</h5>
|
||||
<p>
|
||||
Browse demo without the subscription system. This demo with suit for regular license. Some functions for default
|
||||
howdy account are restricted. Feel free to create your own account with 1 GB upload limit.
|
||||
</p>
|
||||
|
||||
<h3>Frequently asked</h3>
|
||||
|
||||
<h5><strong>Is there any future plan for the mobile app?</strong></h5>
|
||||
<p>
|
||||
Yes, partially, but it depends on how VueFileManager sales will perform. We have to earn some money for mobile
|
||||
development. If it goes well, then we can start work on mobile development. So please buy some more licenses to
|
||||
support further development. Thank you, you are the best!
|
||||
</p>
|
||||
|
||||
<h5><strong>Do you have any future plans to integrate FTP upload?</strong></h5>
|
||||
<p>We don’t have any plan to support FTP uploading, it’s out of scope.</p>
|
||||
<p>
|
||||
When you upload file via app, the app must process the file, create database record, attach it to the owner of the
|
||||
file, move file to storage directory where are stored other user files and any other related functions must run,
|
||||
this can’t be done when user upload file via ftp. This will need to build another software for the server part, but
|
||||
this does not pay off in terms of development costs and benefits for our focused users.
|
||||
</p>
|
||||
<p>
|
||||
But, you can upload files without trouble in any size via VueFileManager, we support chunk upload in browser and
|
||||
multipart upload for your s3 storage disk to manage big files. With this you are able to upload files in the tens of
|
||||
gigabytes.
|
||||
</p>
|
||||
@@ -8,33 +8,59 @@
|
||||
],
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^7.2",
|
||||
"cartalyst/stripe-laravel": "^12.0",
|
||||
"doctrine/dbal": "^2.10",
|
||||
"fideloper/proxy": "^4.0",
|
||||
"fruitcake/laravel-cors": "^1.0",
|
||||
"php": "^8.0.2",
|
||||
"ext-json": "*",
|
||||
"ext-pdo": "*",
|
||||
"beyondcode/laravel-websockets": "^1.13",
|
||||
"brianium/paratest": "^6.4.1",
|
||||
"cocur/slugify": "^4.1",
|
||||
"doctrine/dbal": "^2.13.7",
|
||||
"fruitcake/laravel-cors": "^2.0.5",
|
||||
"gabrielelana/byte-units": "^0.5.0",
|
||||
"intervention/image": "^2.5",
|
||||
"guzzlehttp/guzzle": "^7.4.1",
|
||||
"intervention/image": "^2.7.1",
|
||||
"jaybizzle/laravel-crawler-detect": "^1.2",
|
||||
"kyslik/column-sortable": "^6.3",
|
||||
"laravel/cashier": "^12.0",
|
||||
"laravel/framework": "^7.0",
|
||||
"laravel/passport": "^8.4",
|
||||
"laravel/scout": "^7.2",
|
||||
"laravel/tinker": "^2.0",
|
||||
"laravel/ui": "^2.0",
|
||||
"league/flysystem-aws-s3-v3": "^1.0",
|
||||
"league/flysystem-cached-adapter": "^1.0",
|
||||
"teamtnt/laravel-scout-tntsearch-driver": "^8.3"
|
||||
"kyslik/column-sortable": "^6.4.1",
|
||||
"laravel/fortify": "^1.12.0",
|
||||
"laravel/framework": "^9.2",
|
||||
"laravel/sanctum": "^2.14.2",
|
||||
"laravel/socialite": "^5.5.1",
|
||||
"laravel/tinker": "^2.7",
|
||||
"laravel/ui": "^3.4.2",
|
||||
"league/flysystem-aws-s3-v3": "^3.0.9",
|
||||
"league/flysystem-ftp": "^3.0",
|
||||
"makingcg/subscription": "^1.0.7",
|
||||
"matthewbdaly/laravel-azure-storage": "^2.0",
|
||||
"pusher/pusher-php-server": "^7.0",
|
||||
"spatie/data-transfer-object": "^3.7.3",
|
||||
"spatie/laravel-backup": "^8.0.8",
|
||||
"spatie/laravel-query-builder": "^5.0.0",
|
||||
"spatie/laravel-queueable-action": "^2.13.1",
|
||||
"spatie/laravel-tail": "^4.4.0",
|
||||
"stechstudio/laravel-zipstream": "^4.5",
|
||||
"symfony/http-client": "^6.0",
|
||||
"symfony/mailgun-mailer": "^6.0",
|
||||
"symfony/postmark-mailer": "^6.0",
|
||||
"teamtnt/laravel-scout-tntsearch-driver": "^11.6",
|
||||
"vimeo/psalm": "^4.19.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"barryvdh/laravel-ide-helper": "^2.7",
|
||||
"facade/ignition": "^2.0",
|
||||
"fzaninotto/faker": "^1.4",
|
||||
"mockery/mockery": "^1.0",
|
||||
"nunomaduro/collision": "^4.1",
|
||||
"phpunit/phpunit": "^8.5"
|
||||
"barryvdh/laravel-ide-helper": "^2.12.1",
|
||||
"friendsofphp/php-cs-fixer": "^3.5.0",
|
||||
"spatie/laravel-ignition": "^1.0",
|
||||
"nunomaduro/larastan": "^0.7.15",
|
||||
"nunomaduro/collision": "^6.1",
|
||||
"phpunit/phpunit": "^9.5.16",
|
||||
"mockery/mockery": "^1.5.0",
|
||||
"fakerphp/faker": "^1.19.0",
|
||||
"ext-json": "*"
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/VueFileManager/subscription.git"
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"optimize-autoloader": true,
|
||||
"preferred-install": "dist",
|
||||
@@ -47,15 +73,19 @@
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"App\\": "app/"
|
||||
"App\\" : "src/App/",
|
||||
"Domain\\" : "src/Domain/",
|
||||
"Support\\" : "src/Support/",
|
||||
"Database\\Factories\\": "database/factories/",
|
||||
"Database\\Seeders\\": "database/seeders/"
|
||||
},
|
||||
"classmap": [
|
||||
"database/seeds",
|
||||
"database/factories"
|
||||
],
|
||||
"files": [
|
||||
"app/Http//Helpers/helpers.php",
|
||||
"app/Http//Helpers/subscription.php"
|
||||
"src/Support/errors.php",
|
||||
"src/Support/helpers.php"
|
||||
]
|
||||
},
|
||||
"autoload-dev": {
|
||||
@@ -75,6 +105,7 @@
|
||||
],
|
||||
"post-create-project-cmd": [
|
||||
"@php artisan key:generate --ansi"
|
||||
]
|
||||
],
|
||||
"format": "vendor/bin/php-cs-fixer fix --allow-risky=yes"
|
||||
}
|
||||
}
|
||||
|
||||
13685
composer.lock
generated
13685
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,6 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Name
|
||||
@@ -135,7 +134,6 @@ return [
|
||||
*/
|
||||
|
||||
'providers' => [
|
||||
|
||||
/*
|
||||
* Laravel Framework Service Providers...
|
||||
*/
|
||||
@@ -163,8 +161,9 @@ return [
|
||||
Illuminate\View\ViewServiceProvider::class,
|
||||
|
||||
TeamTNT\Scout\TNTSearchScoutServiceProvider::class,
|
||||
Laravel\Socialite\SocialiteServiceProvider::class,
|
||||
Intervention\Image\ImageServiceProvider::class,
|
||||
Laravel\Passport\PassportServiceProvider::class,
|
||||
App\Providers\FortifyServiceProvider::class,
|
||||
|
||||
/*
|
||||
* Package Service Providers...
|
||||
@@ -175,10 +174,9 @@ return [
|
||||
*/
|
||||
App\Providers\AppServiceProvider::class,
|
||||
App\Providers\AuthServiceProvider::class,
|
||||
// App\Providers\BroadcastServiceProvider::class,
|
||||
App\Providers\BroadcastServiceProvider::class,
|
||||
App\Providers\EventServiceProvider::class,
|
||||
App\Providers\RouteServiceProvider::class,
|
||||
|
||||
],
|
||||
|
||||
/*
|
||||
@@ -193,7 +191,6 @@ return [
|
||||
*/
|
||||
|
||||
'aliases' => [
|
||||
|
||||
'App' => Illuminate\Support\Facades\App::class,
|
||||
'Arr' => Illuminate\Support\Arr::class,
|
||||
'Artisan' => Illuminate\Support\Facades\Artisan::class,
|
||||
@@ -232,35 +229,26 @@ return [
|
||||
'Image' => Intervention\Image\Facades\Image::class,
|
||||
'Stripe' => Cartalyst\Stripe\Laravel\Facades\Stripe::class,
|
||||
'Crawler' => Jaybizzle\LaravelCrawlerDetect\Facades\LaravelCrawlerDetect::class,
|
||||
'Socialite' => Laravel\Socialite\Facades\Socialite::class,
|
||||
],
|
||||
|
||||
'deploy_secret' => env('APP_DEPLOY_SECRET'),
|
||||
'deploy_branch' => env('APP_DEPLOY_BRANCH'),
|
||||
|
||||
'debug_blacklist' => [
|
||||
'_ENV' => [
|
||||
'APP_KEY',
|
||||
|
||||
'DB_USERNAME',
|
||||
'DB_PASSWORD',
|
||||
'REDIS_PASSWORD',
|
||||
'MAIL_PASSWORD',
|
||||
|
||||
'PUSHER_APP_KEY',
|
||||
'PUSHER_APP_SECRET',
|
||||
|
||||
'PASSPORT_CLIENT_ID',
|
||||
'PASSPORT_CLIENT_SECRET',
|
||||
|
||||
'AWS_SECRET_ACCESS_KEY',
|
||||
'AWS_ACCESS_KEY_ID',
|
||||
|
||||
'S3_SECRET_ACCESS_KEY',
|
||||
'S3_ACCESS_KEY_ID',
|
||||
'DO_SPACES_KEY',
|
||||
'DO_SPACES_SECRET',
|
||||
|
||||
'WASABI_KEY',
|
||||
'WASABI_SECRET',
|
||||
|
||||
'BACKBLAZE_KEY',
|
||||
'BACKBLAZE_SECRET',
|
||||
],
|
||||
@@ -278,8 +266,8 @@ return [
|
||||
'PASSPORT_CLIENT_ID',
|
||||
'PASSPORT_CLIENT_SECRET',
|
||||
|
||||
'AWS_SECRET_ACCESS_KEY',
|
||||
'AWS_ACCESS_KEY_ID',
|
||||
'S3_SECRET_ACCESS_KEY',
|
||||
'S3_ACCESS_KEY_ID',
|
||||
|
||||
'DO_SPACES_KEY',
|
||||
'DO_SPACES_SECRET',
|
||||
@@ -294,5 +282,4 @@ return [
|
||||
'password',
|
||||
],
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Authentication Defaults
|
||||
@@ -14,7 +13,7 @@ return [
|
||||
*/
|
||||
|
||||
'defaults' => [
|
||||
'guard' => 'web',
|
||||
'guard' => 'web',
|
||||
'passwords' => 'users',
|
||||
],
|
||||
|
||||
@@ -37,13 +36,14 @@ return [
|
||||
|
||||
'guards' => [
|
||||
'web' => [
|
||||
'driver' => 'session',
|
||||
'driver' => 'session',
|
||||
'provider' => 'users',
|
||||
],
|
||||
|
||||
'api' => [
|
||||
'driver' => 'passport',
|
||||
'driver' => 'token',
|
||||
'provider' => 'users',
|
||||
'hash' => false,
|
||||
],
|
||||
],
|
||||
|
||||
@@ -67,7 +67,7 @@ return [
|
||||
'providers' => [
|
||||
'users' => [
|
||||
'driver' => 'eloquent',
|
||||
'model' => App\User::class,
|
||||
'model' => App\Users\Models\User::class,
|
||||
],
|
||||
|
||||
// 'users' => [
|
||||
@@ -94,8 +94,8 @@ return [
|
||||
'passwords' => [
|
||||
'users' => [
|
||||
'provider' => 'users',
|
||||
'table' => 'password_resets',
|
||||
'expire' => 60,
|
||||
'table' => 'password_resets',
|
||||
'expire' => 60,
|
||||
'throttle' => 60,
|
||||
],
|
||||
],
|
||||
@@ -112,5 +112,4 @@ return [
|
||||
*/
|
||||
|
||||
'password_timeout' => 10800,
|
||||
|
||||
];
|
||||
|
||||
246
config/backup.php
Normal file
246
config/backup.php
Normal file
@@ -0,0 +1,246 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'backup' => [
|
||||
/*
|
||||
* The name of this application. You can use this name to monitor
|
||||
* the backups.
|
||||
*/
|
||||
'name' => 'app-backup',
|
||||
|
||||
'source' => [
|
||||
'files' => [
|
||||
/*
|
||||
* The list of directories and files that will be included in the backup.
|
||||
*/
|
||||
'include' => [
|
||||
base_path(),
|
||||
],
|
||||
|
||||
/*
|
||||
* These directories and files will be excluded from the backup.
|
||||
*
|
||||
* Directories used by the backup process will automatically be excluded.
|
||||
*/
|
||||
'exclude' => [
|
||||
base_path('vendor'),
|
||||
base_path('node_modules'),
|
||||
],
|
||||
|
||||
/*
|
||||
* Determines if symlinks should be followed.
|
||||
*/
|
||||
'follow_links' => false,
|
||||
|
||||
/*
|
||||
* Determines if it should avoid unreadable folders.
|
||||
*/
|
||||
'ignore_unreadable_directories' => false,
|
||||
|
||||
/*
|
||||
* This path is used to make directories in resulting zip-file relative
|
||||
* Set to `null` to include complete absolute path
|
||||
* Example: base_path()
|
||||
*/
|
||||
'relative_path' => null,
|
||||
],
|
||||
|
||||
/*
|
||||
* The names of the connections to the databases that should be backed up
|
||||
* MySQL, PostgreSQL, SQLite and Mongo databases are supported.
|
||||
*
|
||||
* The content of the database dump may be customized for each connection
|
||||
* by adding a 'dump' key to the connection settings in config/database.php.
|
||||
* E.g.
|
||||
* 'mysql' => [
|
||||
* ...
|
||||
* 'dump' => [
|
||||
* 'excludeTables' => [
|
||||
* 'table_to_exclude_from_backup',
|
||||
* 'another_table_to_exclude'
|
||||
* ]
|
||||
* ],
|
||||
* ],
|
||||
*
|
||||
* If you are using only InnoDB tables on a MySQL server, you can
|
||||
* also supply the useSingleTransaction option to avoid table locking.
|
||||
*
|
||||
* E.g.
|
||||
* 'mysql' => [
|
||||
* ...
|
||||
* 'dump' => [
|
||||
* 'useSingleTransaction' => true,
|
||||
* ],
|
||||
* ],
|
||||
*
|
||||
* For a complete list of available customization options, see https://github.com/spatie/db-dumper
|
||||
*/
|
||||
'databases' => [
|
||||
'mysql',
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
* The database dump can be compressed to decrease diskspace usage.
|
||||
*
|
||||
* Out of the box Laravel-backup supplies
|
||||
* Spatie\DbDumper\Compressors\GzipCompressor::class.
|
||||
*
|
||||
* You can also create custom compressor. More info on that here:
|
||||
* https://github.com/spatie/db-dumper#using-compression
|
||||
*
|
||||
* If you do not want any compressor at all, set it to null.
|
||||
*/
|
||||
'database_dump_compressor' => null,
|
||||
|
||||
/*
|
||||
* The file extension used for the database dump files.
|
||||
*
|
||||
* If not specified, the file extension will be .archive for MongoDB and .sql for all other databases
|
||||
* The file extension should be specified without a leading .
|
||||
*/
|
||||
'database_dump_file_extension' => '',
|
||||
|
||||
'destination' => [
|
||||
/*
|
||||
* The filename prefix used for the backup zip file.
|
||||
*/
|
||||
'filename_prefix' => 'backup-',
|
||||
|
||||
/*
|
||||
* The disk names on which the backups will be stored.
|
||||
*/
|
||||
'disks' => [
|
||||
env('FILESYSTEM_DISK', 'local'),
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
* The directory where the temporary files will be stored.
|
||||
*/
|
||||
'temporary_directory' => storage_path('app/backup-temp'),
|
||||
|
||||
/*
|
||||
* The password to be used for archive encryption.
|
||||
* Set to `null` to disable encryption.
|
||||
*/
|
||||
'password' => env('BACKUP_ARCHIVE_PASSWORD', null),
|
||||
|
||||
/*
|
||||
* The encryption algorithm to be used for archive encryption.
|
||||
* You can set it to `null` or `false` to disable encryption.
|
||||
*
|
||||
* When set to 'default', we'll use ZipArchive::EM_AES_256 if it is
|
||||
* available on your system.
|
||||
*/
|
||||
'encryption' => 'default',
|
||||
],
|
||||
|
||||
/*
|
||||
* You can get notified when specific events occur. Out of the box you can use 'mail' and 'slack'.
|
||||
* For Slack you need to install laravel/slack-notification-channel.
|
||||
*
|
||||
* You can also use your own notification classes, just make sure the class is named after one of
|
||||
* the `Spatie\Backup\Events` classes.
|
||||
*/
|
||||
'notifications' => [
|
||||
'notifications' => [
|
||||
\Spatie\Backup\Notifications\Notifications\BackupHasFailedNotification::class => ['mail'],
|
||||
\Spatie\Backup\Notifications\Notifications\UnhealthyBackupWasFoundNotification::class => ['mail'],
|
||||
\Spatie\Backup\Notifications\Notifications\CleanupHasFailedNotification::class => ['mail'],
|
||||
\Spatie\Backup\Notifications\Notifications\BackupWasSuccessfulNotification::class => ['mail'],
|
||||
\Spatie\Backup\Notifications\Notifications\HealthyBackupWasFoundNotification::class => ['mail'],
|
||||
\Spatie\Backup\Notifications\Notifications\CleanupWasSuccessfulNotification::class => ['mail'],
|
||||
],
|
||||
|
||||
/*
|
||||
* Here you can specify the notifiable to which the notifications should be sent. The default
|
||||
* notifiable will use the variables specified in this config file.
|
||||
*/
|
||||
'notifiable' => \Spatie\Backup\Notifications\Notifiable::class,
|
||||
|
||||
'mail' => [
|
||||
'to' => env('MAIL_FROM_ADDRESS', 'hello@example.com'),
|
||||
|
||||
'from' => [
|
||||
'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'),
|
||||
'name' => env('MAIL_FROM_NAME', 'Example'),
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
* Here you can specify which backups should be monitored.
|
||||
* If a backup does not meet the specified requirements the
|
||||
* UnHealthyBackupWasFound event will be fired.
|
||||
*/
|
||||
'monitor_backups' => [
|
||||
[
|
||||
'name' => env('APP_NAME', 'vuefilemanager-backup'),
|
||||
'disks' => [
|
||||
env('FILESYSTEM_DISK', 'local'),
|
||||
],
|
||||
'health_checks' => [
|
||||
\Spatie\Backup\Tasks\Monitor\HealthChecks\MaximumAgeInDays::class => 1,
|
||||
\Spatie\Backup\Tasks\Monitor\HealthChecks\MaximumStorageInMegabytes::class => 5000,
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
[
|
||||
'name' => 'name of the second app',
|
||||
'disks' => ['local', 's3'],
|
||||
'health_checks' => [
|
||||
\Spatie\Backup\Tasks\Monitor\HealthChecks\MaximumAgeInDays::class => 1,
|
||||
\Spatie\Backup\Tasks\Monitor\HealthChecks\MaximumStorageInMegabytes::class => 5000,
|
||||
],
|
||||
],
|
||||
*/
|
||||
],
|
||||
|
||||
'cleanup' => [
|
||||
/*
|
||||
* The strategy that will be used to cleanup old backups. The default strategy
|
||||
* will keep all backups for a certain amount of days. After that period only
|
||||
* a daily backup will be kept. After that period only weekly backups will
|
||||
* be kept and so on.
|
||||
*
|
||||
* No matter how you configure it the default strategy will never
|
||||
* delete the newest backup.
|
||||
*/
|
||||
'strategy' => \Spatie\Backup\Tasks\Cleanup\Strategies\DefaultStrategy::class,
|
||||
|
||||
'default_strategy' => [
|
||||
/*
|
||||
* The number of days for which backups must be kept.
|
||||
*/
|
||||
'keep_all_backups_for_days' => 10,
|
||||
|
||||
/*
|
||||
* The number of days for which daily backups must be kept.
|
||||
*/
|
||||
'keep_daily_backups_for_days' => 16,
|
||||
|
||||
/*
|
||||
* The number of weeks for which one weekly backup must be kept.
|
||||
*/
|
||||
'keep_weekly_backups_for_weeks' => 8,
|
||||
|
||||
/*
|
||||
* The number of months for which one monthly backup must be kept.
|
||||
*/
|
||||
'keep_monthly_backups_for_months' => 4,
|
||||
|
||||
/*
|
||||
* The number of years for which one yearly backup must be kept.
|
||||
*/
|
||||
'keep_yearly_backups_for_years' => 2,
|
||||
|
||||
/*
|
||||
* After cleaning up the backups remove the oldest backup until
|
||||
* this amount of megabytes has been reached.
|
||||
*/
|
||||
'delete_oldest_backups_when_using_more_megabytes_than' => 5000,
|
||||
],
|
||||
],
|
||||
];
|
||||
@@ -1,7 +1,6 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Broadcaster
|
||||
@@ -29,20 +28,22 @@ return [
|
||||
*/
|
||||
|
||||
'connections' => [
|
||||
|
||||
'pusher' => [
|
||||
'driver' => 'pusher',
|
||||
'key' => env('PUSHER_APP_KEY'),
|
||||
'secret' => env('PUSHER_APP_SECRET'),
|
||||
'app_id' => env('PUSHER_APP_ID'),
|
||||
'driver' => 'pusher',
|
||||
'key' => env('PUSHER_APP_KEY'),
|
||||
'secret' => env('PUSHER_APP_SECRET'),
|
||||
'app_id' => env('PUSHER_APP_ID'),
|
||||
'options' => [
|
||||
'cluster' => env('PUSHER_APP_CLUSTER'),
|
||||
'useTLS' => true,
|
||||
'cluster' => env('PUSHER_APP_CLUSTER'),
|
||||
'encrypted' => true,
|
||||
'host' => env('PUSHER_APP_HOST'),
|
||||
'port' => env('PUSHER_APP_PORT'),
|
||||
'scheme' => env('PUSHER_APP_TLS', true) ? 'https' : 'http',
|
||||
],
|
||||
],
|
||||
|
||||
'redis' => [
|
||||
'driver' => 'redis',
|
||||
'driver' => 'redis',
|
||||
'connection' => 'default',
|
||||
],
|
||||
|
||||
@@ -53,7 +54,5 @@ return [
|
||||
'null' => [
|
||||
'driver' => 'null',
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Cache Store
|
||||
@@ -32,7 +31,6 @@ return [
|
||||
*/
|
||||
|
||||
'stores' => [
|
||||
|
||||
'apc' => [
|
||||
'driver' => 'apc',
|
||||
],
|
||||
@@ -42,20 +40,20 @@ return [
|
||||
],
|
||||
|
||||
'database' => [
|
||||
'driver' => 'database',
|
||||
'table' => 'cache',
|
||||
'driver' => 'database',
|
||||
'table' => 'cache',
|
||||
'connection' => null,
|
||||
],
|
||||
|
||||
'file' => [
|
||||
'driver' => 'file',
|
||||
'path' => storage_path('framework/cache/data'),
|
||||
'path' => storage_path('framework/cache/data'),
|
||||
],
|
||||
|
||||
'memcached' => [
|
||||
'driver' => 'memcached',
|
||||
'driver' => 'memcached',
|
||||
'persistent_id' => env('MEMCACHED_PERSISTENT_ID'),
|
||||
'sasl' => [
|
||||
'sasl' => [
|
||||
env('MEMCACHED_USERNAME'),
|
||||
env('MEMCACHED_PASSWORD'),
|
||||
],
|
||||
@@ -64,27 +62,26 @@ return [
|
||||
],
|
||||
'servers' => [
|
||||
[
|
||||
'host' => env('MEMCACHED_HOST', '127.0.0.1'),
|
||||
'port' => env('MEMCACHED_PORT', 11211),
|
||||
'host' => env('MEMCACHED_HOST', '127.0.0.1'),
|
||||
'port' => env('MEMCACHED_PORT', 11211),
|
||||
'weight' => 100,
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
'redis' => [
|
||||
'driver' => 'redis',
|
||||
'driver' => 'redis',
|
||||
'connection' => 'cache',
|
||||
],
|
||||
|
||||
'dynamodb' => [
|
||||
'driver' => 'dynamodb',
|
||||
'key' => env('AWS_ACCESS_KEY_ID'),
|
||||
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
||||
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
|
||||
'table' => env('DYNAMODB_CACHE_TABLE', 'cache'),
|
||||
'driver' => 'dynamodb',
|
||||
'key' => env('S3_ACCESS_KEY_ID'),
|
||||
'secret' => env('S3_SECRET_ACCESS_KEY'),
|
||||
'region' => env('S3_DEFAULT_REGION', 'us-east-1'),
|
||||
'table' => env('DYNAMODB_CACHE_TABLE', 'cache'),
|
||||
'endpoint' => env('DYNAMODB_ENDPOINT'),
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
/*
|
||||
@@ -99,5 +96,4 @@ return [
|
||||
*/
|
||||
|
||||
'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache'),
|
||||
|
||||
];
|
||||
|
||||
@@ -1,129 +0,0 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Stripe Keys
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The Stripe publishable key and secret key give you access to Stripe's
|
||||
| API. The "publishable" key is typically used when interacting with
|
||||
| Stripe.js while the "secret" key accesses private API endpoints.
|
||||
|
|
||||
*/
|
||||
|
||||
'key' => env('STRIPE_KEY'),
|
||||
|
||||
'secret' => env('STRIPE_SECRET'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cashier Path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This is the base URI path where Cashier's views, such as the payment
|
||||
| verification screen, will be available from. You're free to tweak
|
||||
| this path according to your preferences and application design.
|
||||
|
|
||||
*/
|
||||
|
||||
'path' => env('CASHIER_PATH', 'stripe'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Stripe Webhooks
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Your Stripe webhook secret is used to prevent unauthorized requests to
|
||||
| your Stripe webhook handling controllers. The tolerance setting will
|
||||
| check the drift between the current time and the signed request's.
|
||||
|
|
||||
*/
|
||||
|
||||
'webhook' => [
|
||||
'secret' => env('STRIPE_WEBHOOK_SECRET'),
|
||||
'tolerance' => env('STRIPE_WEBHOOK_TOLERANCE', 300),
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cashier Model
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This is the model in your application that implements the Billable trait
|
||||
| provided by Cashier. It will serve as the primary model you use while
|
||||
| interacting with Cashier related methods, subscriptions, and so on.
|
||||
|
|
||||
*/
|
||||
|
||||
'model' => env('CASHIER_MODEL', App\User::class),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Currency
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This is the default currency that will be used when generating charges
|
||||
| from your application. Of course, you are welcome to use any of the
|
||||
| various world currencies that are currently supported via Stripe.
|
||||
|
|
||||
*/
|
||||
|
||||
'currency' => env('CASHIER_CURRENCY', 'usd'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Currency Locale
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This is the default locale in which your money values are formatted in
|
||||
| for display. To utilize other locales besides the default en locale
|
||||
| verify you have the "intl" PHP extension installed on the system.
|
||||
|
|
||||
*/
|
||||
|
||||
'currency_locale' => env('CASHIER_CURRENCY_LOCALE', 'en'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Payment Confirmation Notification
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If this setting is enabled, Cashier will automatically notify customers
|
||||
| whose payments require additional verification. You should listen to
|
||||
| Stripe's webhooks in order for this feature to function correctly.
|
||||
|
|
||||
*/
|
||||
|
||||
'payment_notification' => env('CASHIER_PAYMENT_NOTIFICATION'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Invoice Paper Size
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option is the default paper size for all invoices generated using
|
||||
| Cashier. You are free to customize this settings based on the usual
|
||||
| paper size used by the customers using your Laravel applications.
|
||||
|
|
||||
| Supported sizes: 'letter', 'legal', 'A4'
|
||||
|
|
||||
*/
|
||||
|
||||
'paper' => env('CASHIER_PAPER', 'letter'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Stripe Logger
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This setting defines which logging channel will be used by the Stripe
|
||||
| library to write log messages. You are free to specify any of your
|
||||
| logging channels listed inside the "logging" configuration file.
|
||||
|
|
||||
*/
|
||||
|
||||
'logger' => env('CASHIER_LOGGER'),
|
||||
|
||||
];
|
||||
@@ -22,81 +22,191 @@ return [
|
||||
],
|
||||
],
|
||||
'content' => [
|
||||
[
|
||||
'name' => 'section_features',
|
||||
'value' => '1',
|
||||
'regular' => [
|
||||
[
|
||||
'name' => 'section_features',
|
||||
'value' => 1,
|
||||
],
|
||||
[
|
||||
'name' => 'section_feature_boxes',
|
||||
'value' => 1,
|
||||
],
|
||||
[
|
||||
'name' => 'section_get_started',
|
||||
'value' => 1,
|
||||
],
|
||||
[
|
||||
'name' => 'header_title',
|
||||
'value' => 'Simple <span class="text-theme">&</span> Powerful Personal Cloud Storage',
|
||||
],
|
||||
[
|
||||
'name' => 'header_description',
|
||||
'value' => 'Your private cloud storage software build on Laravel & Vue.js. No limits & no monthly fees. Truly freedom.',
|
||||
],
|
||||
[
|
||||
'name' => 'features_title',
|
||||
'value' => 'The Fastest Growing <span class="text-theme">File Manager</span> on the CodeCanyon Market',
|
||||
],
|
||||
[
|
||||
'name' => 'features_description',
|
||||
'value' => 'Your private cloud storage software build on Laravel & Vue.js. No limits & no monthly fees. Truly freedom.',
|
||||
],
|
||||
[
|
||||
'name' => 'feature_title_1',
|
||||
'value' => 'Truly Freedom',
|
||||
],
|
||||
[
|
||||
'name' => 'feature_description_1',
|
||||
'value' => 'You have full control over VueFileManager, no third authorities will control your service or usage, only you.',
|
||||
],
|
||||
[
|
||||
'name' => 'feature_title_2',
|
||||
'value' => 'The Sky is the Limit',
|
||||
],
|
||||
[
|
||||
'name' => 'feature_description_2',
|
||||
'value' => 'VueFileManager is cloud storage software. You have to install and running application on your own server hosting.',
|
||||
],
|
||||
[
|
||||
'name' => 'feature_title_3',
|
||||
'value' => 'No Monthly Fees',
|
||||
],
|
||||
[
|
||||
'name' => 'feature_description_3',
|
||||
'value' => 'When you running VueFileManager on your own server hosting, anybody can\'t control your content or resell your user data. Your data is safe.',
|
||||
],
|
||||
[
|
||||
'name' => 'get_started_title',
|
||||
'value' => 'Ready to Get <span class="text-theme">Started</span><br> With Us?',
|
||||
],
|
||||
[
|
||||
'name' => 'get_started_description',
|
||||
'value' => 'Your private cloud storage software build on Laravel & Vue.js. No limits & no monthly fees. Truly freedom.',
|
||||
],
|
||||
[
|
||||
'name' => 'footer_content',
|
||||
'value' => '© 2022 Simple & Powerful Personal Cloud Storage. Developed by <a href="https://hi5ve.digital" target="_blank">Hi5Ve.Digital</a>',
|
||||
],
|
||||
[
|
||||
'name' => 'allow_homepage',
|
||||
'value' => 1,
|
||||
],
|
||||
[
|
||||
'name' => 'allowed_adsense',
|
||||
'value' => 0,
|
||||
],
|
||||
[
|
||||
'name' => 'allowed_recaptcha',
|
||||
'value' => 0,
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'section_feature_boxes',
|
||||
'value' => '1',
|
||||
],
|
||||
[
|
||||
'name' => 'section_pricing_content',
|
||||
'value' => '1',
|
||||
],
|
||||
[
|
||||
'name' => 'section_get_started',
|
||||
'value' => '1',
|
||||
],
|
||||
[
|
||||
'name' => 'header_title',
|
||||
'value' => 'Simple <span style="color: #41B883">&</span> Powerful Personal Cloud Storage',
|
||||
],
|
||||
[
|
||||
'name' => 'header_description',
|
||||
'value' => 'Your private cloud storage software build on Laravel & Vue.js. No limits & no monthly fees. Truly freedom.',
|
||||
],
|
||||
[
|
||||
'name' => 'features_title',
|
||||
'value' => 'The Fastest Growing <span style="color: #41B883">File Manager</span> on the CodeCanyon Market',
|
||||
],
|
||||
[
|
||||
'name' => 'features_description',
|
||||
'value' => 'Your private cloud storage software build on Laravel & Vue.js. No limits & no monthly fees. Truly freedom.',
|
||||
],
|
||||
[
|
||||
'name' => 'feature_title_1',
|
||||
'value' => 'Truly Freedom',
|
||||
],
|
||||
[
|
||||
'name' => 'feature_description_1',
|
||||
'value' => 'You have full control over VueFileManager, no third authorities will control your service or usage, only you.',
|
||||
],
|
||||
[
|
||||
'name' => 'feature_title_2',
|
||||
'value' => 'The Sky is the Limit',
|
||||
],
|
||||
[
|
||||
'name' => 'feature_description_2',
|
||||
'value' => 'VueFileManager is cloud storage software. You have to install and running application on your own server hosting.',
|
||||
],
|
||||
[
|
||||
'name' => 'feature_title_3',
|
||||
'value' => 'No Monthly Fees',
|
||||
],
|
||||
[
|
||||
'name' => 'feature_description_3',
|
||||
'value' => 'When you running VueFileManager on your own server hosting, anybody can\'t control your content or resell your user data. Your data is safe.',
|
||||
],
|
||||
[
|
||||
'name' => 'pricing_title',
|
||||
'value' => 'Pick the <span style="color: #41B883;">Best Plan</span> For Your Needs',
|
||||
],
|
||||
[
|
||||
'name' => 'pricing_description',
|
||||
'value' => 'Your private cloud storage software build on Laravel & Vue.js. No limits & no monthly fees. Truly freedom.',
|
||||
],
|
||||
[
|
||||
'name' => 'get_started_title',
|
||||
'value' => 'Ready to Get <span style="color: #41B883">Started</span><br> With Us?',
|
||||
],
|
||||
[
|
||||
'name' => 'get_started_description',
|
||||
'value' => 'Your private cloud storage software build on Laravel & Vue.js. No limits & no monthly fees. Truly freedom.',
|
||||
],
|
||||
[
|
||||
'name' => 'footer_content',
|
||||
'value' => '© 2020 Simple & Powerful Personal Cloud Storage. Developed by <a href="https://hi5ve.digital" target="_blank">Hi5Ve.Digital</a>',
|
||||
'extended' => [
|
||||
[
|
||||
'name' => 'section_features',
|
||||
'value' => 1,
|
||||
],
|
||||
[
|
||||
'name' => 'section_feature_boxes',
|
||||
'value' => 1,
|
||||
],
|
||||
[
|
||||
'name' => 'section_pricing_content',
|
||||
'value' => 1,
|
||||
],
|
||||
[
|
||||
'name' => 'section_get_started',
|
||||
'value' => 1,
|
||||
],
|
||||
[
|
||||
'name' => 'header_title',
|
||||
'value' => 'Simple <span class="text-theme">&</span> Powerful Personal Cloud Storage',
|
||||
],
|
||||
[
|
||||
'name' => 'header_description',
|
||||
'value' => 'Your private cloud storage software build on Laravel & Vue.js. No limits & no monthly fees. Truly freedom.',
|
||||
],
|
||||
[
|
||||
'name' => 'features_title',
|
||||
'value' => 'The Fastest Growing <span class="text-theme">File Manager</span> on the CodeCanyon Market',
|
||||
],
|
||||
[
|
||||
'name' => 'features_description',
|
||||
'value' => 'Your private cloud storage software build on Laravel & Vue.js. No limits & no monthly fees. Truly freedom.',
|
||||
],
|
||||
[
|
||||
'name' => 'feature_title_1',
|
||||
'value' => 'Truly Freedom',
|
||||
],
|
||||
[
|
||||
'name' => 'feature_description_1',
|
||||
'value' => 'You have full control over VueFileManager, no third authorities will control your service or usage, only you.',
|
||||
],
|
||||
[
|
||||
'name' => 'feature_title_2',
|
||||
'value' => 'The Sky is the Limit',
|
||||
],
|
||||
[
|
||||
'name' => 'feature_description_2',
|
||||
'value' => 'VueFileManager is cloud storage software. You have to install and running application on your own server hosting.',
|
||||
],
|
||||
[
|
||||
'name' => 'feature_title_3',
|
||||
'value' => 'No Monthly Fees',
|
||||
],
|
||||
[
|
||||
'name' => 'feature_description_3',
|
||||
'value' => 'When you running VueFileManager on your own server hosting, anybody can\'t control your content or resell your user data. Your data is safe.',
|
||||
],
|
||||
[
|
||||
'name' => 'pricing_title',
|
||||
'value' => 'Pick the <span class="text-theme">Best Plan</span> For Your Needs',
|
||||
],
|
||||
[
|
||||
'name' => 'pricing_description',
|
||||
'value' => 'Your private cloud storage software build on Laravel & Vue.js. No limits & no monthly fees. Truly freedom.',
|
||||
],
|
||||
[
|
||||
'name' => 'get_started_title',
|
||||
'value' => 'Ready to Get <span class="text-theme">Started</span><br> With Us?',
|
||||
],
|
||||
[
|
||||
'name' => 'get_started_description',
|
||||
'value' => 'Your private cloud storage software build on Laravel & Vue.js. No limits & no monthly fees. Truly freedom.',
|
||||
],
|
||||
[
|
||||
'name' => 'footer_content',
|
||||
'value' => '© 2022 Simple & Powerful Personal Cloud Storage. Developed by <a href="https://hi5ve.digital" target="_blank" class="text-theme">Hi5Ve.Digital</a>',
|
||||
],
|
||||
[
|
||||
'name' => 'allowed_adsense',
|
||||
'value' => 0,
|
||||
],
|
||||
[
|
||||
'name' => 'allowed_recaptcha',
|
||||
'value' => 0,
|
||||
],
|
||||
|
||||
// Subscription
|
||||
[
|
||||
'name' => 'paypal_payment_description',
|
||||
'value' => 'Available PayPal Credit, Debit or Credit Card.',
|
||||
],
|
||||
[
|
||||
'name' => 'paystack_payment_description',
|
||||
'value' => 'Available Bank Account, USSD, Mobile Money, Apple Pay.',
|
||||
],
|
||||
[
|
||||
'name' => 'stripe_payment_description',
|
||||
'value' => 'Available credit card or Apple Pay.',
|
||||
],
|
||||
[
|
||||
'name' => 'allowed_registration_bonus',
|
||||
'value' => 0,
|
||||
],
|
||||
[
|
||||
'name' => 'registration_bonus_amount',
|
||||
'value' => 0,
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
];
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Laravel CORS Options
|
||||
|
||||
11
config/custom-language-translations.php
Normal file
11
config/custom-language-translations.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Place here your custom translations for your project.
|
||||
* These translation will be automatically seeded after you
|
||||
* run setup:dev script or installing app via Setup Wizard Tool
|
||||
*/
|
||||
|
||||
return [
|
||||
'custom' => 'translation',
|
||||
];
|
||||
@@ -3,7 +3,6 @@
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Database Connection Name
|
||||
@@ -34,63 +33,66 @@ return [
|
||||
*/
|
||||
|
||||
'connections' => [
|
||||
|
||||
'sqlite' => [
|
||||
'driver' => 'sqlite',
|
||||
'url' => env('DATABASE_URL'),
|
||||
'database' => env('DB_DATABASE', database_path('database.sqlite')),
|
||||
'prefix' => '',
|
||||
'driver' => 'sqlite',
|
||||
'url' => env('DATABASE_URL'),
|
||||
'database' => env('DB_DATABASE', database_path('database.sqlite')),
|
||||
'prefix' => '',
|
||||
'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
|
||||
],
|
||||
|
||||
'mysql' => [
|
||||
'driver' => 'mysql',
|
||||
'url' => env('DATABASE_URL'),
|
||||
'host' => env('DB_HOST', '127.0.0.1'),
|
||||
'port' => env('DB_PORT', '3306'),
|
||||
'database' => env('DB_DATABASE', 'forge'),
|
||||
'username' => env('DB_USERNAME', 'forge'),
|
||||
'password' => env('DB_PASSWORD', ''),
|
||||
'unix_socket' => env('DB_SOCKET', ''),
|
||||
'charset' => 'utf8mb4',
|
||||
'collation' => 'utf8mb4_unicode_ci',
|
||||
'prefix' => '',
|
||||
'driver' => 'mysql',
|
||||
'url' => env('DATABASE_URL'),
|
||||
'host' => env('DB_HOST', '127.0.0.1'),
|
||||
'port' => env('DB_PORT', '3306'),
|
||||
'database' => env('DB_DATABASE', 'forge'),
|
||||
'username' => env('DB_USERNAME', 'forge'),
|
||||
'password' => env('DB_PASSWORD', ''),
|
||||
'unix_socket' => env('DB_SOCKET', ''),
|
||||
'charset' => 'utf8mb4',
|
||||
'collation' => 'utf8mb4_unicode_ci',
|
||||
'prefix' => '',
|
||||
'prefix_indexes' => true,
|
||||
'strict' => true,
|
||||
'engine' => null,
|
||||
'options' => extension_loaded('pdo_mysql') ? array_filter([
|
||||
'strict' => true,
|
||||
'engine' => null,
|
||||
'options' => extension_loaded('pdo_mysql') ? array_filter([
|
||||
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
|
||||
]) : [],
|
||||
'dump' => [
|
||||
'dump_binary_path' => env('DB_MYSQLDUMP_PATH', 'usr/bin'), // only the path, so without `mysqldump` or `pg_dump`
|
||||
'use_single_transaction',
|
||||
'timeout' => 360,
|
||||
],
|
||||
],
|
||||
|
||||
'pgsql' => [
|
||||
'driver' => 'pgsql',
|
||||
'url' => env('DATABASE_URL'),
|
||||
'host' => env('DB_HOST', '127.0.0.1'),
|
||||
'port' => env('DB_PORT', '5432'),
|
||||
'database' => env('DB_DATABASE', 'forge'),
|
||||
'username' => env('DB_USERNAME', 'forge'),
|
||||
'password' => env('DB_PASSWORD', ''),
|
||||
'charset' => 'utf8',
|
||||
'prefix' => '',
|
||||
'driver' => 'pgsql',
|
||||
'url' => env('DATABASE_URL'),
|
||||
'host' => env('DB_HOST', '127.0.0.1'),
|
||||
'port' => env('DB_PORT', '5432'),
|
||||
'database' => env('DB_DATABASE', 'forge'),
|
||||
'username' => env('DB_USERNAME', 'forge'),
|
||||
'password' => env('DB_PASSWORD', ''),
|
||||
'charset' => 'utf8',
|
||||
'prefix' => '',
|
||||
'prefix_indexes' => true,
|
||||
'schema' => 'public',
|
||||
'sslmode' => 'prefer',
|
||||
'schema' => 'public',
|
||||
'sslmode' => 'prefer',
|
||||
],
|
||||
|
||||
'sqlsrv' => [
|
||||
'driver' => 'sqlsrv',
|
||||
'url' => env('DATABASE_URL'),
|
||||
'host' => env('DB_HOST', 'localhost'),
|
||||
'port' => env('DB_PORT', '1433'),
|
||||
'database' => env('DB_DATABASE', 'forge'),
|
||||
'username' => env('DB_USERNAME', 'forge'),
|
||||
'password' => env('DB_PASSWORD', ''),
|
||||
'charset' => 'utf8',
|
||||
'prefix' => '',
|
||||
'driver' => 'sqlsrv',
|
||||
'url' => env('DATABASE_URL'),
|
||||
'host' => env('DB_HOST', 'localhost'),
|
||||
'port' => env('DB_PORT', '1433'),
|
||||
'database' => env('DB_DATABASE', 'forge'),
|
||||
'username' => env('DB_USERNAME', 'forge'),
|
||||
'password' => env('DB_PASSWORD', ''),
|
||||
'charset' => 'utf8',
|
||||
'prefix' => '',
|
||||
'prefix_indexes' => true,
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
/*
|
||||
@@ -118,30 +120,27 @@ return [
|
||||
*/
|
||||
|
||||
'redis' => [
|
||||
|
||||
'client' => env('REDIS_CLIENT', 'phpredis'),
|
||||
|
||||
'options' => [
|
||||
'cluster' => env('REDIS_CLUSTER', 'redis'),
|
||||
'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
|
||||
'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
|
||||
],
|
||||
|
||||
'default' => [
|
||||
'url' => env('REDIS_URL'),
|
||||
'host' => env('REDIS_HOST', '127.0.0.1'),
|
||||
'url' => env('REDIS_URL'),
|
||||
'host' => env('REDIS_HOST', '127.0.0.1'),
|
||||
'password' => env('REDIS_PASSWORD', null),
|
||||
'port' => env('REDIS_PORT', '6379'),
|
||||
'port' => env('REDIS_PORT', '6379'),
|
||||
'database' => env('REDIS_DB', '0'),
|
||||
],
|
||||
|
||||
'cache' => [
|
||||
'url' => env('REDIS_URL'),
|
||||
'host' => env('REDIS_HOST', '127.0.0.1'),
|
||||
'url' => env('REDIS_URL'),
|
||||
'host' => env('REDIS_HOST', '127.0.0.1'),
|
||||
'password' => env('REDIS_PASSWORD', null),
|
||||
'port' => env('REDIS_PORT', '6379'),
|
||||
'port' => env('REDIS_PORT', '6379'),
|
||||
'database' => env('REDIS_CACHE_DB', '1'),
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
557
config/disposable-email-providers.php
Normal file
557
config/disposable-email-providers.php
Normal file
@@ -0,0 +1,557 @@
|
||||
<?php
|
||||
|
||||
// List based on michenriksen/disposable-email-provider-domains
|
||||
// https://gist.github.com/michenriksen/8710649
|
||||
|
||||
return [
|
||||
'0815.ru',
|
||||
'0wnd.net',
|
||||
'0wnd.org',
|
||||
'10minutemail.co.za',
|
||||
'10minutemail.com',
|
||||
'123-m.com',
|
||||
'1fsdfdsfsdf.tk',
|
||||
'1pad.de',
|
||||
'20minutemail.com',
|
||||
'21cn.com',
|
||||
'2fdgdfgdfgdf.tk',
|
||||
'2prong.com',
|
||||
'30minutemail.com',
|
||||
'33mail.com',
|
||||
'3trtretgfrfe.tk',
|
||||
'4gfdsgfdgfd.tk',
|
||||
'4warding.com',
|
||||
'5ghgfhfghfgh.tk',
|
||||
'6hjgjhgkilkj.tk',
|
||||
'6paq.com',
|
||||
'7tags.com',
|
||||
'9ox.net',
|
||||
'a-bc.net',
|
||||
'agedmail.com',
|
||||
'ama-trade.de',
|
||||
'amilegit.com',
|
||||
'amiri.net',
|
||||
'amiriindustries.com',
|
||||
'anonmails.de',
|
||||
'anonymbox.com',
|
||||
'antichef.com',
|
||||
'antichef.net',
|
||||
'antireg.ru',
|
||||
'antispam.de',
|
||||
'antispammail.de',
|
||||
'armyspy.com',
|
||||
'artman-conception.com',
|
||||
'azmeil.tk',
|
||||
'baxomale.ht.cx',
|
||||
'beefmilk.com',
|
||||
'bigstring.com',
|
||||
'binkmail.com',
|
||||
'bio-muesli.net',
|
||||
'bobmail.info',
|
||||
'bodhi.lawlita.com',
|
||||
'bofthew.com',
|
||||
'bootybay.de',
|
||||
'boun.cr',
|
||||
'bouncr.com',
|
||||
'breakthru.com',
|
||||
'brefmail.com',
|
||||
'bsnow.net',
|
||||
'bspamfree.org',
|
||||
'bugmenot.com',
|
||||
'bund.us',
|
||||
'burstmail.info',
|
||||
'buymoreplays.com',
|
||||
'byom.de',
|
||||
'c2.hu',
|
||||
'card.zp.ua',
|
||||
'casualdx.com',
|
||||
'cek.pm',
|
||||
'centermail.com',
|
||||
'centermail.net',
|
||||
'chammy.info',
|
||||
'childsavetrust.org',
|
||||
'chogmail.com',
|
||||
'choicemail1.com',
|
||||
'clixser.com',
|
||||
'cmail.net',
|
||||
'cmail.org',
|
||||
'coldemail.info',
|
||||
'cool.fr.nf',
|
||||
'courriel.fr.nf',
|
||||
'courrieltemporaire.com',
|
||||
'crapmail.org',
|
||||
'cust.in',
|
||||
'cuvox.de',
|
||||
'd3p.dk',
|
||||
'dacoolest.com',
|
||||
'dandikmail.com',
|
||||
'dayrep.com',
|
||||
'dcemail.com',
|
||||
'deadaddress.com',
|
||||
'deadspam.com',
|
||||
'delikkt.de',
|
||||
'despam.it',
|
||||
'despammed.com',
|
||||
'devnullmail.com',
|
||||
'dfgh.net',
|
||||
'digitalsanctuary.com',
|
||||
'dingbone.com',
|
||||
'disposableaddress.com',
|
||||
'disposableemailaddresses.com',
|
||||
'disposableinbox.com',
|
||||
'dispose.it',
|
||||
'dispostable.com',
|
||||
'dodgeit.com',
|
||||
'dodgit.com',
|
||||
'donemail.ru',
|
||||
'dontreg.com',
|
||||
'dontsendmespam.de',
|
||||
'drdrb.net',
|
||||
'dump-email.info',
|
||||
'dumpandjunk.com',
|
||||
'dumpyemail.com',
|
||||
'e-mail.com',
|
||||
'e-mail.org',
|
||||
'e4ward.com',
|
||||
'easytrashmail.com',
|
||||
'einmalmail.de',
|
||||
'einrot.com',
|
||||
'eintagsmail.de',
|
||||
'emailgo.de',
|
||||
'emailias.com',
|
||||
'emaillime.com',
|
||||
'emailsensei.com',
|
||||
'emailtemporanea.com',
|
||||
'emailtemporanea.net',
|
||||
'emailtemporar.ro',
|
||||
'emailtemporario.com.br',
|
||||
'emailthe.net',
|
||||
'emailtmp.com',
|
||||
'emailwarden.com',
|
||||
'emailx.at.hm',
|
||||
'emailxfer.com',
|
||||
'emeil.in',
|
||||
'emeil.ir',
|
||||
'emz.net',
|
||||
'ero-tube.org',
|
||||
'evopo.com',
|
||||
'explodemail.com',
|
||||
'express.net.ua',
|
||||
'eyepaste.com',
|
||||
'fakeinbox.com',
|
||||
'fakeinformation.com',
|
||||
'fansworldwide.de',
|
||||
'fantasymail.de',
|
||||
'fightallspam.com',
|
||||
'filzmail.com',
|
||||
'fivemail.de',
|
||||
'fleckens.hu',
|
||||
'frapmail.com',
|
||||
'friendlymail.co.uk',
|
||||
'fuckingduh.com',
|
||||
'fudgerub.com',
|
||||
'fyii.de',
|
||||
'garliclife.com',
|
||||
'gehensiemirnichtaufdensack.de',
|
||||
'get2mail.fr',
|
||||
'getairmail.com',
|
||||
'getmails.eu',
|
||||
'getonemail.com',
|
||||
'giantmail.de',
|
||||
'girlsundertheinfluence.com',
|
||||
'gishpuppy.com',
|
||||
'gmial.com',
|
||||
'goemailgo.com',
|
||||
'gotmail.net',
|
||||
'gotmail.org',
|
||||
'gotti.otherinbox.com',
|
||||
'great-host.in',
|
||||
'greensloth.com',
|
||||
'grr.la',
|
||||
'gsrv.co.uk',
|
||||
'guerillamail.biz',
|
||||
'guerillamail.com',
|
||||
'guerrillamail.biz',
|
||||
'guerrillamail.com',
|
||||
'guerrillamail.de',
|
||||
'guerrillamail.info',
|
||||
'guerrillamail.net',
|
||||
'guerrillamail.org',
|
||||
'guerrillamailblock.com',
|
||||
'gustr.com',
|
||||
'harakirimail.com',
|
||||
'hat-geld.de',
|
||||
'hatespam.org',
|
||||
'herp.in',
|
||||
'hidemail.de',
|
||||
'hidzz.com',
|
||||
'hmamail.com',
|
||||
'hopemail.biz',
|
||||
'ieh-mail.de',
|
||||
'ikbenspamvrij.nl',
|
||||
'imails.info',
|
||||
'inbax.tk',
|
||||
'inbox.si',
|
||||
'inboxalias.com',
|
||||
'inboxclean.com',
|
||||
'inboxclean.org',
|
||||
'infocom.zp.ua',
|
||||
'instant-mail.de',
|
||||
'ip6.li',
|
||||
'irish2me.com',
|
||||
'iwi.net',
|
||||
'jetable.com',
|
||||
'jetable.fr.nf',
|
||||
'jetable.net',
|
||||
'jetable.org',
|
||||
'jnxjn.com',
|
||||
'jourrapide.com',
|
||||
'jsrsolutions.com',
|
||||
'kasmail.com',
|
||||
'kaspop.com',
|
||||
'killmail.com',
|
||||
'killmail.net',
|
||||
'klassmaster.com',
|
||||
'klzlk.com',
|
||||
'koszmail.pl',
|
||||
'kurzepost.de',
|
||||
'lawlita.com',
|
||||
'letthemeatspam.com',
|
||||
'lhsdv.com',
|
||||
'lifebyfood.com',
|
||||
'link2mail.net',
|
||||
'litedrop.com',
|
||||
'lol.ovpn.to',
|
||||
'lolfreak.net',
|
||||
'lookugly.com',
|
||||
'lortemail.dk',
|
||||
'lr78.com',
|
||||
'lroid.com',
|
||||
'lukop.dk',
|
||||
'm21.cc',
|
||||
'mail-filter.com',
|
||||
'mail-temporaire.fr',
|
||||
'mail.by',
|
||||
'mail.mezimages.net',
|
||||
'mail.zp.ua',
|
||||
'mail1a.de',
|
||||
'mail21.cc',
|
||||
'mail2rss.org',
|
||||
'mail333.com',
|
||||
'mailbidon.com',
|
||||
'mailbiz.biz',
|
||||
'mailblocks.com',
|
||||
'mailbucket.org',
|
||||
'mailcat.biz',
|
||||
'mailcatch.com',
|
||||
'mailde.de',
|
||||
'mailde.info',
|
||||
'maildrop.cc',
|
||||
'maileimer.de',
|
||||
'mailexpire.com',
|
||||
'mailfa.tk',
|
||||
'mailforspam.com',
|
||||
'mailfreeonline.com',
|
||||
'mailguard.me',
|
||||
'mailin8r.com',
|
||||
'mailinater.com',
|
||||
'mailinator.com',
|
||||
'mailinator.net',
|
||||
'mailinator.org',
|
||||
'mailinator2.com',
|
||||
'mailincubator.com',
|
||||
'mailismagic.com',
|
||||
'mailme.lv',
|
||||
'mailme24.com',
|
||||
'mailmetrash.com',
|
||||
'mailmoat.com',
|
||||
'mailms.com',
|
||||
'mailnesia.com',
|
||||
'mailnull.com',
|
||||
'mailorg.org',
|
||||
'mailpick.biz',
|
||||
'mailrock.biz',
|
||||
'mailscrap.com',
|
||||
'mailshell.com',
|
||||
'mailsiphon.com',
|
||||
'mailtemp.info',
|
||||
'mailtome.de',
|
||||
'mailtothis.com',
|
||||
'mailtrash.net',
|
||||
'mailtv.net',
|
||||
'mailtv.tv',
|
||||
'mailzilla.com',
|
||||
'makemetheking.com',
|
||||
'manybrain.com',
|
||||
'mbx.cc',
|
||||
'mega.zik.dj',
|
||||
'meinspamschutz.de',
|
||||
'meltmail.com',
|
||||
'messagebeamer.de',
|
||||
'mezimages.net',
|
||||
'ministry-of-silly-walks.de',
|
||||
'mintemail.com',
|
||||
'misterpinball.de',
|
||||
'moncourrier.fr.nf',
|
||||
'monemail.fr.nf',
|
||||
'monmail.fr.nf',
|
||||
'monumentmail.com',
|
||||
'mt2009.com',
|
||||
'mt2014.com',
|
||||
'mycard.net.ua',
|
||||
'mycleaninbox.net',
|
||||
'mymail-in.net',
|
||||
'mypacks.net',
|
||||
'mypartyclip.de',
|
||||
'myphantomemail.com',
|
||||
'mysamp.de',
|
||||
'mytempemail.com',
|
||||
'mytempmail.com',
|
||||
'mytrashmail.com',
|
||||
'nabuma.com',
|
||||
'neomailbox.com',
|
||||
'nepwk.com',
|
||||
'nervmich.net',
|
||||
'nervtmich.net',
|
||||
'netmails.com',
|
||||
'netmails.net',
|
||||
'neverbox.com',
|
||||
'nice-4u.com',
|
||||
'nincsmail.hu',
|
||||
'nnh.com',
|
||||
'no-spam.ws',
|
||||
'noblepioneer.com',
|
||||
'nomail.pw',
|
||||
'nomail.xl.cx',
|
||||
'nomail2me.com',
|
||||
'nomorespamemails.com',
|
||||
'nospam.ze.tc',
|
||||
'nospam4.us',
|
||||
'nospamfor.us',
|
||||
'nospammail.net',
|
||||
'notmailinator.com',
|
||||
'nowhere.org',
|
||||
'nowmymail.com',
|
||||
'nurfuerspam.de',
|
||||
'nus.edu.sg',
|
||||
'objectmail.com',
|
||||
'obobbo.com',
|
||||
'odnorazovoe.ru',
|
||||
'oneoffemail.com',
|
||||
'onewaymail.com',
|
||||
'onlatedotcom.info',
|
||||
'online.ms',
|
||||
'opayq.com',
|
||||
'ordinaryamerican.net',
|
||||
'otherinbox.com',
|
||||
'ovpn.to',
|
||||
'owlpic.com',
|
||||
'pancakemail.com',
|
||||
'pcusers.otherinbox.com',
|
||||
'pjjkp.com',
|
||||
'plexolan.de',
|
||||
'poczta.onet.pl',
|
||||
'politikerclub.de',
|
||||
'poofy.org',
|
||||
'pookmail.com',
|
||||
'privacy.net',
|
||||
'privatdemail.net',
|
||||
'proxymail.eu',
|
||||
'prtnx.com',
|
||||
'putthisinyourspamdatabase.com',
|
||||
'putthisinyourspamdatabase.com',
|
||||
'qq.com',
|
||||
'quickinbox.com',
|
||||
'rcpt.at',
|
||||
'reallymymail.com',
|
||||
'realtyalerts.ca',
|
||||
'recode.me',
|
||||
'recursor.net',
|
||||
'reliable-mail.com',
|
||||
'rhyta.com',
|
||||
'rmqkr.net',
|
||||
'royal.net',
|
||||
'rtrtr.com',
|
||||
's0ny.net',
|
||||
'safe-mail.net',
|
||||
'safersignup.de',
|
||||
'safetymail.info',
|
||||
'safetypost.de',
|
||||
'saynotospams.com',
|
||||
'schafmail.de',
|
||||
'schrott-email.de',
|
||||
'secretemail.de',
|
||||
'secure-mail.biz',
|
||||
'senseless-entertainment.com',
|
||||
'services391.com',
|
||||
'sharklasers.com',
|
||||
'shieldemail.com',
|
||||
'shiftmail.com',
|
||||
'shitmail.me',
|
||||
'shitware.nl',
|
||||
'shmeriously.com',
|
||||
'shortmail.net',
|
||||
'sibmail.com',
|
||||
'sinnlos-mail.de',
|
||||
'slapsfromlastnight.com',
|
||||
'slaskpost.se',
|
||||
'smashmail.de',
|
||||
'smellfear.com',
|
||||
'snakemail.com',
|
||||
'sneakemail.com',
|
||||
'sneakmail.de',
|
||||
'snkmail.com',
|
||||
'sofimail.com',
|
||||
'solvemail.info',
|
||||
'sogetthis.com',
|
||||
'soodonims.com',
|
||||
'spam4.me',
|
||||
'spamail.de',
|
||||
'spamarrest.com',
|
||||
'spambob.net',
|
||||
'spambog.ru',
|
||||
'spambox.us',
|
||||
'spamcannon.com',
|
||||
'spamcannon.net',
|
||||
'spamcon.org',
|
||||
'spamcorptastic.com',
|
||||
'spamcowboy.com',
|
||||
'spamcowboy.net',
|
||||
'spamcowboy.org',
|
||||
'spamday.com',
|
||||
'spamex.com',
|
||||
'spamfree.eu',
|
||||
'spamfree24.com',
|
||||
'spamfree24.de',
|
||||
'spamfree24.org',
|
||||
'spamgoes.in',
|
||||
'spamgourmet.com',
|
||||
'spamgourmet.net',
|
||||
'spamgourmet.org',
|
||||
'spamherelots.com',
|
||||
'spamherelots.com',
|
||||
'spamhereplease.com',
|
||||
'spamhereplease.com',
|
||||
'spamhole.com',
|
||||
'spamify.com',
|
||||
'spaml.de',
|
||||
'spammotel.com',
|
||||
'spamobox.com',
|
||||
'spamslicer.com',
|
||||
'spamspot.com',
|
||||
'spamthis.co.uk',
|
||||
'spamtroll.net',
|
||||
'speed.1s.fr',
|
||||
'spoofmail.de',
|
||||
'stuffmail.de',
|
||||
'super-auswahl.de',
|
||||
'supergreatmail.com',
|
||||
'supermailer.jp',
|
||||
'superrito.com',
|
||||
'superstachel.de',
|
||||
'suremail.info',
|
||||
'talkinator.com',
|
||||
'teewars.org',
|
||||
'teleworm.com',
|
||||
'teleworm.us',
|
||||
'temp-mail.org',
|
||||
'temp-mail.ru',
|
||||
'tempe-mail.com',
|
||||
'tempemail.co.za',
|
||||
'tempemail.com',
|
||||
'tempemail.net',
|
||||
'tempemail.net',
|
||||
'tempinbox.co.uk',
|
||||
'tempinbox.com',
|
||||
'tempmail.eu',
|
||||
'tempmaildemo.com',
|
||||
'tempmailer.com',
|
||||
'tempmailer.de',
|
||||
'tempomail.fr',
|
||||
'temporaryemail.net',
|
||||
'temporaryforwarding.com',
|
||||
'temporaryinbox.com',
|
||||
'temporarymailaddress.com',
|
||||
'tempthe.net',
|
||||
'thankyou2010.com',
|
||||
'thc.st',
|
||||
'thelimestones.com',
|
||||
'thisisnotmyrealemail.com',
|
||||
'thismail.net',
|
||||
'throwawayemailaddress.com',
|
||||
'tilien.com',
|
||||
'tittbit.in',
|
||||
'tizi.com',
|
||||
'tmailinator.com',
|
||||
'toomail.biz',
|
||||
'topranklist.de',
|
||||
'tradermail.info',
|
||||
'trash-mail.at',
|
||||
'trash-mail.com',
|
||||
'trash-mail.de',
|
||||
'trash2009.com',
|
||||
'trashdevil.com',
|
||||
'trashemail.de',
|
||||
'trashmail.at',
|
||||
'trashmail.com',
|
||||
'trashmail.de',
|
||||
'trashmail.me',
|
||||
'trashmail.net',
|
||||
'trashmail.org',
|
||||
'trashymail.com',
|
||||
'trialmail.de',
|
||||
'trillianpro.com',
|
||||
'twinmail.de',
|
||||
'tyldd.com',
|
||||
'uggsrock.com',
|
||||
'umail.net',
|
||||
'uroid.com',
|
||||
'us.af',
|
||||
'venompen.com',
|
||||
'veryrealemail.com',
|
||||
'viditag.com',
|
||||
'viralplays.com',
|
||||
'vpn.st',
|
||||
'vsimcard.com',
|
||||
'vubby.com',
|
||||
'wasteland.rfc822.org',
|
||||
'webemail.me',
|
||||
'weg-werf-email.de',
|
||||
'wegwerf-emails.de',
|
||||
'wegwerfadresse.de',
|
||||
'wegwerfemail.com',
|
||||
'wegwerfemail.de',
|
||||
'wegwerfmail.de',
|
||||
'wegwerfmail.info',
|
||||
'wegwerfmail.net',
|
||||
'wegwerfmail.org',
|
||||
'wh4f.org',
|
||||
'whyspam.me',
|
||||
'willhackforfood.biz',
|
||||
'willselfdestruct.com',
|
||||
'winemaven.info',
|
||||
'wronghead.com',
|
||||
'www.e4ward.com',
|
||||
'www.mailinator.com',
|
||||
'wwwnew.eu',
|
||||
'x.ip6.li',
|
||||
'xagloo.com',
|
||||
'xemaps.com',
|
||||
'xents.com',
|
||||
'xmaily.com',
|
||||
'xoxy.net',
|
||||
'yep.it',
|
||||
'yogamaven.com',
|
||||
'yopmail.com',
|
||||
'yopmail.fr',
|
||||
'yopmail.net',
|
||||
'yourdomain.com',
|
||||
'yuurok.com',
|
||||
'z1p.biz',
|
||||
'za.com',
|
||||
'zehnminuten.de',
|
||||
'zehnminutenmail.de',
|
||||
'zippymail.info',
|
||||
'zoemail.net',
|
||||
'zomg.info',
|
||||
];
|
||||
@@ -1,7 +1,6 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Filesystem Disk
|
||||
@@ -13,20 +12,7 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('FILESYSTEM_DRIVER', 'local'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Cloud Filesystem Disk
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Many applications store files both locally and in the cloud. For this
|
||||
| reason, you may specify a default "cloud" driver here. This driver
|
||||
| will be bound as the Cloud disk implementation in the container.
|
||||
|
|
||||
*/
|
||||
|
||||
'cloud' => env('FILESYSTEM_CLOUD', 's3'),
|
||||
'default' => env('FILESYSTEM_DISK', 'local'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@@ -42,55 +28,39 @@ return [
|
||||
*/
|
||||
|
||||
'disks' => [
|
||||
|
||||
'local' => [
|
||||
'driver' => 'local',
|
||||
'root' => storage_path('app'),
|
||||
'root' => storage_path('app'),
|
||||
],
|
||||
|
||||
'public' => [
|
||||
'driver' => 'local',
|
||||
'root' => storage_path('app/public'),
|
||||
'url' => env('APP_URL').'/storage',
|
||||
'driver' => 'local',
|
||||
'root' => storage_path('app/public'),
|
||||
'url' => env('APP_URL').'/storage',
|
||||
'visibility' => 'public',
|
||||
],
|
||||
|
||||
's3' => [
|
||||
'driver' => 's3',
|
||||
'key' => env('AWS_ACCESS_KEY_ID'),
|
||||
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
||||
'region' => env('AWS_DEFAULT_REGION'),
|
||||
'bucket' => env('AWS_BUCKET'),
|
||||
'endpoint' => env('AWS_URL'),
|
||||
'driver' => 's3',
|
||||
'key' => env('S3_ACCESS_KEY_ID'),
|
||||
'secret' => env('S3_SECRET_ACCESS_KEY'),
|
||||
'region' => env('S3_DEFAULT_REGION'),
|
||||
'bucket' => env('S3_BUCKET'),
|
||||
'endpoint' => env('S3_URL'),
|
||||
'visibility' => 'private',
|
||||
],
|
||||
|
||||
'spaces' => [
|
||||
'driver' => 's3',
|
||||
'key' => env('DO_SPACES_KEY'),
|
||||
'secret' => env('DO_SPACES_SECRET'),
|
||||
'endpoint' => env('DO_SPACES_ENDPOINT'),
|
||||
'region' => env('DO_SPACES_REGION'),
|
||||
'bucket' => env('DO_SPACES_BUCKET'),
|
||||
'ftp' => [
|
||||
'driver' => 'ftp',
|
||||
'host' => env('FTP_HOST'),
|
||||
'username' => env('FTP_USERNAME'),
|
||||
'password' => env('FTP_PASSWORD'),
|
||||
],
|
||||
|
||||
'wasabi' => [
|
||||
'driver' => 's3',
|
||||
'key' => env('WASABI_KEY'),
|
||||
'secret' => env('WASABI_SECRET'),
|
||||
'endpoint' => env('WASABI_ENDPOINT'),
|
||||
'region' => env('WASABI_REGION'),
|
||||
'bucket' => env('WASABI_BUCKET'),
|
||||
'azure' => [
|
||||
'driver' => 'azure',
|
||||
'name' => env('AZURE_STORAGE_NAME'),
|
||||
'key' => env('AZURE_STORAGE_KEY'),
|
||||
'container' => env('AZURE_STORAGE_CONTAINER'),
|
||||
'url' => env('AZURE_STORAGE_URL'),
|
||||
'prefix' => null,
|
||||
'connection_string' => env('AZURE_STORAGE_CONNECTION_STRING'), // optional, will override default endpoint builder
|
||||
],
|
||||
|
||||
'backblaze' => [
|
||||
'driver' => 's3',
|
||||
'key' => env('BACKBLAZE_KEY'),
|
||||
'secret' => env('BACKBLAZE_SECRET'),
|
||||
'endpoint' => env('BACKBLAZE_ENDPOINT'),
|
||||
'region' => env('BACKBLAZE_REGION'),
|
||||
'bucket' => env('BACKBLAZE_BUCKET'),
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
139
config/fortify.php
Normal file
139
config/fortify.php
Normal file
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
use Laravel\Fortify\Features;
|
||||
use App\Providers\RouteServiceProvider;
|
||||
|
||||
return [
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Fortify Guard
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify which authentication guard Fortify will use while
|
||||
| authenticating users. This value should correspond with one of your
|
||||
| guards that is already present in your "auth" configuration file.
|
||||
|
|
||||
*/
|
||||
|
||||
'guard' => 'web',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Fortify Password Broker
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify which password broker Fortify can use when a user
|
||||
| is resetting their password. This configured value should match one
|
||||
| of your password brokers setup in your "auth" configuration file.
|
||||
|
|
||||
*/
|
||||
|
||||
'passwords' => 'users',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Username / Email
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This value defines which model attribute should be considered as your
|
||||
| application's "username" field. Typically, this might be the email
|
||||
| address of the users but you are free to change this value here.
|
||||
|
|
||||
| Out of the box, Fortify expects forgot password and reset password
|
||||
| requests to have a field named 'email'. If the application uses
|
||||
| another name for the field you may define it below as needed.
|
||||
|
|
||||
*/
|
||||
|
||||
'username' => 'email',
|
||||
|
||||
'email' => 'email',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Home Path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure the path where users will get redirected during
|
||||
| authentication or password reset when the operations are successful
|
||||
| and the user is authenticated. You are free to change this value.
|
||||
|
|
||||
*/
|
||||
|
||||
'home' => RouteServiceProvider::HOME,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Fortify Routes Prefix / Subdomain
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify which prefix Fortify will assign to all the routes
|
||||
| that it registers with the application. If necessary, you may change
|
||||
| subdomain under which all of the Fortify routes will be available.
|
||||
|
|
||||
*/
|
||||
|
||||
'prefix' => '',
|
||||
|
||||
'domain' => null,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Fortify Routes Middleware
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify which middleware Fortify will assign to the routes
|
||||
| that it registers with the application. If necessary, you may change
|
||||
| these middleware but typically this provided default is preferred.
|
||||
|
|
||||
*/
|
||||
|
||||
'middleware' => ['web'],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Rate Limiting
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| By default, Fortify will throttle logins to five requests per minute for
|
||||
| every email and IP address combination. However, if you would like to
|
||||
| specify a custom rate limiter to call then you may specify it here.
|
||||
|
|
||||
*/
|
||||
|
||||
'limiters' => [
|
||||
'login' => 'login',
|
||||
'two-factor' => 'two-factor',
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Register View Routes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify if the routes returning views should be disabled as
|
||||
| you may not need them when building your own application. This may be
|
||||
| especially true if you're writing a custom single-page application.
|
||||
|
|
||||
*/
|
||||
|
||||
'views' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Features
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Some of the Fortify features are optional. You may disable the features
|
||||
| by removing them from this array. You're free to only remove some of
|
||||
| these features or you can even remove all of these if you need to.
|
||||
|
|
||||
*/
|
||||
|
||||
'features' => [
|
||||
Features::twoFactorAuthentication([
|
||||
'confirm' => true,
|
||||
'confirmPassword' => true,
|
||||
]),
|
||||
],
|
||||
];
|
||||
@@ -1,7 +1,6 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Hash Driver
|
||||
@@ -44,9 +43,8 @@ return [
|
||||
*/
|
||||
|
||||
'argon' => [
|
||||
'memory' => 1024,
|
||||
'memory' => 1024,
|
||||
'threads' => 2,
|
||||
'time' => 2,
|
||||
'time' => 2,
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
959
config/language-translations.php
Normal file
959
config/language-translations.php
Normal file
@@ -0,0 +1,959 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'extended' => [
|
||||
'plans' => 'Plans',
|
||||
'total' => 'Total',
|
||||
'create_plan' => 'Create Plan',
|
||||
'delete_plan' => 'Delete Plan',
|
||||
'admin_page_plans.disclaimer_delete_plan' => 'You can delete this plan, but, pay attention! Your plan will be deleted, but users who are subscribed with this plan, will be still charged unless they cancel subscription.',
|
||||
'description_optional' => 'Description (optional)',
|
||||
'plan_description' => 'Plan description',
|
||||
'type_plan_name' => 'Type plan name',
|
||||
'plan_name' => 'Plan name',
|
||||
'plan_price' => 'Plan price',
|
||||
'admin_page_plans.form.status_help' => 'Status of your plan availability on website.',
|
||||
'admin_page_plans.form.storage' => 'Storage Capacity in GB',
|
||||
'admin_page_plans.form.storage_helper' => "You have to type only number e.g. value '5' means, user will have 5GB of storage capacity.",
|
||||
'admin_page_plans.form.storage_plac' => 'Storage capacity',
|
||||
'admin_page_plans.subscribers.empty' => 'There is no any subscriber yet.',
|
||||
'subscribers' => 'Subscribers',
|
||||
'settings' => 'Settings',
|
||||
'billing_address' => 'Billing Address',
|
||||
'admin_settings.billings.address_plac' => 'Type your billing address',
|
||||
'billing_city' => 'Billing City',
|
||||
'admin_settings.billings.city_plac' => 'Type your billing city',
|
||||
'admin_settings.billings.company_name' => 'Company Name',
|
||||
'admin_settings.billings.company_name_plac' => 'Type your company name',
|
||||
'admin_settings.billings.country' => 'Billing Country',
|
||||
'admin_settings.billings.country_plac' => 'Select your billing country',
|
||||
'admin_settings.billings.phone_number' => 'Billing Phone Number (optional)',
|
||||
'admin_settings.billings.phone_number_plac' => 'Type your billing phone number',
|
||||
'admin_settings.billings.postal_code' => 'Billing Postal Code',
|
||||
'admin_settings.billings.postal_code_plac' => 'Type your billing postal code',
|
||||
'admin_settings.billings.section_billing' => 'Billing Information',
|
||||
'admin_settings.billings.section_company' => 'Company Information',
|
||||
'admin_settings.billings.state' => 'Billing State',
|
||||
'admin_settings.billings.state_plac' => 'Type your billing state',
|
||||
'admin_settings.billings.vat' => 'VAT Number',
|
||||
'admin_settings.billings.vat_plac' => 'Type your VAT number',
|
||||
'admin_settings.payments.stripe_pub_key' => 'Publishable Key',
|
||||
'admin_settings.payments.stripe_pub_key_plac' => 'Paste your publishable key',
|
||||
'admin_settings.payments.stripe_sec_key' => 'Secret Key',
|
||||
'admin_settings.payments.stripe_sec_key_plac' => 'Paste your secret key',
|
||||
'billings' => 'Billings',
|
||||
'payments' => 'Payments',
|
||||
'mo.' => 'Mo.',
|
||||
'premium' => 'Premium',
|
||||
'invoices' => 'Invoices',
|
||||
'subscription' => 'Subscription',
|
||||
'page_pricing_tables.storage_capacity' => 'Of Storage Capacity',
|
||||
'page_pricing_tables.vat_excluded' => 'Price displayed excludes VAT.',
|
||||
'popup_deleted_plan.title' => 'Plan was deleted',
|
||||
'popup_subscription_cancel.message' => "You'll continue to have access to the features you've paid for until the end of your billing cycle.",
|
||||
'popup_subscription_cancel.title' => 'Subscription Was Canceled',
|
||||
'plan' => 'Plan',
|
||||
'plan_delete' => 'Plan Delete',
|
||||
'plan_settings' => 'Plan Settings',
|
||||
'pricing_plans' => 'Pricing Plans',
|
||||
'toaster.plan_created' => 'Your plan was successfully created!',
|
||||
'toaster.credentials_set' => 'Your {service} credentials was successfully set!',
|
||||
'user_invoices.empty' => "You don't have any invoices yet.",
|
||||
'print_button' => 'Print Document',
|
||||
'invoice' => 'Invoice',
|
||||
'date' => 'Date',
|
||||
'product' => 'Product',
|
||||
'invoice_number' => 'Invoice Number',
|
||||
'seller' => 'Seller',
|
||||
'client' => 'Client',
|
||||
'seller_vat' => 'VAT number',
|
||||
'phone' => 'Phone',
|
||||
'postal_code' => 'Postal code',
|
||||
'price' => 'Price',
|
||||
'charged_features' => 'Charged Features',
|
||||
'team_members' => 'Team Members',
|
||||
'add_max_team_members' => 'Add max team members in number',
|
||||
'max_team_members_total' => 'Up to {value} Team Members',
|
||||
'max_team_members.unlimited' => 'Unlimited Team Members',
|
||||
'max_storage_amount' => '{value} GB Storage Size',
|
||||
'monthly' => 'Monthly',
|
||||
'yearly' => 'Yearly',
|
||||
'month' => 'Month',
|
||||
'year' => 'Year',
|
||||
'bandwidth' => 'Bandwidth',
|
||||
'storage' => 'Storage',
|
||||
'flatFee' => 'Flat Fee',
|
||||
'feature_usage_desc_flatFee' => 'Price for the service.',
|
||||
'feature_usage_desc_bandwidth' => 'Data amount you transferred to/from your account.',
|
||||
'feature_usage_desc_storage' => 'Total storage amount you are using.',
|
||||
'feature_usage_desc_member' => 'Total members you invited to your team folders.',
|
||||
'feature_usage_desc_platform' => 'Total storage amount you are using.',
|
||||
'credit_to_auto_withdraw' => 'You own {credit} in credits that will be automatically withdrawn on your next payment.',
|
||||
'transactions' => 'Transactions',
|
||||
'not_any_transactions' => "There aren't any transactions.",
|
||||
'service' => 'Service',
|
||||
'payed_at' => 'Payed At',
|
||||
'current_estimated_usage' => 'Your current estimated usage:',
|
||||
'payment_was_successfully_received' => 'Your payment was successfully received.',
|
||||
'failed_to_load_paypal' => 'Failed to load the PayPal service',
|
||||
'cancel_payment' => 'Cancel Payment',
|
||||
'not_any_payment_method' => "There isn't any payment method yet.",
|
||||
'select_payment_method' => 'Select Payment Method',
|
||||
'change_your_plan' => 'Change Your Plan',
|
||||
'not_any_plan' => "There isn't any plan yet.",
|
||||
'change_plan' => 'Change Plan',
|
||||
'subscription_changed' => 'Your subscription was successfully changed.',
|
||||
'expires' => 'Expires',
|
||||
'want_to_delete_card_title' => 'Are you sure you want to delete your credit card?',
|
||||
'want_to_delete_card_description' => 'We will no longer settle your payments automatically and you will have to fund your account for the next payments.',
|
||||
'credit_card_deleted' => 'Your credit card was deleted.',
|
||||
'billed_annually' => 'Billed Annually',
|
||||
'restricted_account_warning' => 'Your functionality is restricted. Please review your billing settings.',
|
||||
'subscription_type' => 'Subscription Type',
|
||||
'subscription_type_note' => 'Please do not change in production environment.',
|
||||
'select_subscription_type' => 'Select your subscription type',
|
||||
'subscription_type_change_warn' => 'Are you sure you want to change subscription type?',
|
||||
'subscription_type_change_warn_description' => 'We strongly do not recommend change this value if there is any subscribed user to prevent any failures. You can operate only with one type of subscription and you can not change it on the fly!',
|
||||
'x_days_intervals' => '30 Days intervals',
|
||||
'interval' => 'Interval',
|
||||
'currency' => 'Currency',
|
||||
'allow_pay_by_card' => 'Allow your users pay by their credit card',
|
||||
'paste_webhook_secret' => 'Paste your webhook secret',
|
||||
'configure_your_credentials' => 'Configure Your Credentials',
|
||||
'allow_registration_bonus' => 'Allow Registration Bonus',
|
||||
'allow_registration_bonus_description' => 'Credit user automatically bonus to his balance after registration.',
|
||||
'registration_bonus_amount' => 'The Amount of Registration Bonus',
|
||||
'registration_bonus_amount_description' => 'This bonus will be automatically added when user successfully register his account.',
|
||||
'registration_bonus_amount_' => 'Type registration bonus amount...',
|
||||
'metered_plan' => 'Metered Plan',
|
||||
'metered_plan_description' => 'Your price set up for billing multiple features by user usage.',
|
||||
'plan_details' => 'Plan Details',
|
||||
'copy_webhook_note' => 'Please copy your url and paste it to the service webhook setup.',
|
||||
'webhook_url' => 'Your Webhook URL',
|
||||
'payment_description' => 'Payment Description',
|
||||
'payment_description_note' => 'The description showed below user payment method selection.',
|
||||
'additional_info_about_payment_method_' => 'Describe in short which methods user can pay with this payment method...',
|
||||
'select_plan_currency' => 'Select plan currency',
|
||||
'select_billing_interval' => 'Select billing interval',
|
||||
'features' => 'Features',
|
||||
'bandwidth_per_gb' => 'Bandwidth Price per 1GB',
|
||||
'bandwidth_per_gb_note' => 'Charge your user by the amount of data he upload or download.',
|
||||
'type_bandwidth_price' => 'Type the price per 1GB...',
|
||||
'storage_per_gb' => 'Storage Price per 1GB',
|
||||
'storage_per_gb_note' => 'Charge your user by the amount of data he has stored on the disk per 1GB.',
|
||||
'type_storage_price' => 'Type the price per 1GB...',
|
||||
'member_per_unit' => 'Price per 1 Member',
|
||||
'member_per_unit_note' => 'Charge your user by the total members he use in his Team Folders.',
|
||||
'type_member_price' => 'Type the price per 1 member...',
|
||||
'flat_fee_unit_gb' => 'Flat Fee per Cycle',
|
||||
'flat_fee_unit_gb_note' => 'Charge monthly flat fee.',
|
||||
'type_flat_fee_price' => 'Type the price...',
|
||||
'price_change_not_possible_create_new' => 'Price change is not possible. If you would like to change your price or currency, please feel free to create a new plan.',
|
||||
'metered_billing_settings' => 'Metered Billing Settings',
|
||||
'allow_subscription_payments' => 'Allow Subscription Payments',
|
||||
'allow_subscription_payments_description' => 'User can subscribe to fixed or metered plan',
|
||||
'subscription_payments' => 'Subscription Payments',
|
||||
'free_plan_parameters' => '{storage}GB Free storage space with {members} Team members',
|
||||
'active_until' => 'Active until {date}',
|
||||
'ends_at_date' => 'Ends at {date}',
|
||||
'price_per_month' => '{price} Per Month',
|
||||
'price_per_year' => '{price} Per Year',
|
||||
'balance_will_be_increased' => 'User balance will be increased for the amount above.',
|
||||
'increase_for' => 'Increase user balance for...',
|
||||
'increase_balance' => 'Increase Balance',
|
||||
'balance_was_increased' => 'User balance was successfully increased',
|
||||
'user_dont_have_transactions' => "User doesn't have any transactions yet.",
|
||||
'billing_est.' => 'Billing Est.',
|
||||
'ends_at' => 'Ends At',
|
||||
'renews_at' => 'Renews At',
|
||||
'create_first_plan' => 'Create First Plan',
|
||||
'all_visible_subscriptions_here' => 'All your subscriptions will be visible here',
|
||||
'all_visible_plans_here' => 'All your plans will be visible here',
|
||||
'transaction_will_be_here' => 'All your transactions will be visible here',
|
||||
'latest_transactions' => 'Latest Transactions',
|
||||
'show_all_transactions' => 'Show all transactions',
|
||||
'earnings' => 'Earnings',
|
||||
'records_updated_daily_bases' => 'Records are updated on daily bases.',
|
||||
'till_now' => 'till now',
|
||||
'usage_estimates' => 'Usage Estimates',
|
||||
'payment_method_update_redirect_description' => 'You will be redirected to your payment provider to edit your payment method.',
|
||||
'update_payment_method' => 'Update your Payment Method',
|
||||
'update_payments' => 'Update Payments',
|
||||
'credit_card_stored' => 'Your credit card was stored successfully',
|
||||
'store_my_credit_card' => 'Store My Credit Card',
|
||||
'add_payment_method' => 'Add Payment Method',
|
||||
'auto_settled_credit_card' => 'We are settling your payment automatically via your saved credit card.',
|
||||
'payment_method' => 'Payment Method',
|
||||
'unable_to_charge' => "We are unable to charge your usage. Please register new credit card or fund your account with sufficient amount and we'll give it another try!",
|
||||
'failed_payments' => 'Failed Payments',
|
||||
'upgrade_to_get_more' => 'Upgrade your account to get more.',
|
||||
'free_plan' => 'Free Plan',
|
||||
'want_cancel_subscription' => 'Are you sure you want to cancel subscription?',
|
||||
'upgrade_downgrade_plan' => 'Upgrade or Downgrade Plan',
|
||||
'upgrade_downgrade_plan_description' => 'You can upgrade your plan at any time you want.',
|
||||
'cancel_now' => 'Cancel Now',
|
||||
'cancel_subscription' => 'Cancel Subscription',
|
||||
'cancel_subscription_description' => "You can cancel your subscription now. You'll continue to have access to the features you've paid for until the end of your billing cycle.",
|
||||
'edit_your_subscription' => 'Edit your Subscription',
|
||||
'want_to_delete_alert_description' => 'You will no longer receive any notifications that your billing limit has been exceeded.',
|
||||
'want_to_delete_alert' => 'Are you sure you want to delete your alert?',
|
||||
'alert_set_successfully' => 'Your billing alert was set successfully',
|
||||
'alert_updated' => 'Your billing alert was updated successfully',
|
||||
'set_alert' => 'Set Alert',
|
||||
'update_alert' => 'Update Alert',
|
||||
'deleted_alert' => 'Your billing alert was deleted.',
|
||||
'alert_amount_' => 'Alert Amount...',
|
||||
'billing_alert' => 'Billing Alert',
|
||||
'billing_alert_description' => 'Alert will be triggered after you reach the value above.',
|
||||
'billing_alert_notes' => 'You will receive an email whenever your monthly balance reaches the specified amount above.',
|
||||
'make_payment' => 'Make a Payment',
|
||||
'fund_account_balance' => 'Fund Your Account Balance...',
|
||||
'amount_increase_description' => 'The amount will be increased as soon as we register your charge from payment gateway.',
|
||||
'balance' => 'Balance',
|
||||
'upgrade_account' => 'Upgrade Account',
|
||||
'upgrade_your_account' => 'Upgrade Your Account',
|
||||
'upload_temporarily_disabled' => 'Upload is temporarily disabled',
|
||||
'upload_temporarily_disabled_note' => 'Please review your billing settings.',
|
||||
'create_folder_temporarily_disabled' => 'Folder creation is temporarily disabled',
|
||||
'create_folder_temporarily_disabled_desc' => 'Please review your billing settings.',
|
||||
'download_temporarily_disabled' => 'File download is temporarily disabled',
|
||||
'download_temporarily_disabled_desc' => 'Please review your billing settings.',
|
||||
'billing' => 'Billing',
|
||||
'usage' => 'usage',
|
||||
'charge' => 'Charge',
|
||||
'credit' => 'Credit',
|
||||
'withdrawal' => 'Withdrawal',
|
||||
'interval.year' => 'Yearly',
|
||||
'interval.month' => 'Monthly',
|
||||
'subscriptions' => 'Subscriptions',
|
||||
'show_billing' => 'Show Billing',
|
||||
'billing_alert_reached_short' => 'Billing Alert Reached!',
|
||||
'billing_alert_reached_short_note' => 'The billing alert you set previously has been reached. Please revise your spending.',
|
||||
'billing_alert_reached_long' => 'Your billing alert has been reached!',
|
||||
'billing_alert_reached_long_note' => 'The billing alert you set previously has been reached. Please go to your user account and revise your spending',
|
||||
'you_received_bonus' => 'You Received :bonus',
|
||||
'you_received_bonus_note' => 'You received credit bonus :bonus from us. Happy spending!',
|
||||
'you_received_registration_bonus_note' => 'You received credit bonus :bonus for your registration. Happy spending!',
|
||||
'withdrawal_failed_short' => 'Withdrawal Failed',
|
||||
'withdrawal_failed_short_note' => "Your credit withdrawal for your account didn't go through. Please make sure you have sufficient funds on your account.",
|
||||
'withdrawal_failed_long' => 'Uh-oh! Your credit withdrawal for your pre-paid subscription failed',
|
||||
'withdrawal_failed_long_note' => "It looks like your subscription credit withdrawal for your account didn't go through. Please make sure you have sufficient funds on your account and we'll give it another try!",
|
||||
'fund_your_account' => 'Fund Your Account',
|
||||
'subscription_created_short' => 'Subscription Has Been Created',
|
||||
'subscription_created_short_note' => 'Your subscription :plan has been successfully created',
|
||||
'subscription_created_long' => 'Your subscription :plan has been successfully created',
|
||||
'subscription_created_long_note' => 'You have been successfully subscribed to your :plan subscription. Now you can take full advantage of our platform.',
|
||||
'go_to_subscription' => 'Go to Subscription',
|
||||
'charge_from_card_failed_subject' => 'Uh-oh! Your withdrawal from your credit card for pre-paid subscription failed',
|
||||
'charge_from_card_failed_line' => "It looks like withdrawal from your credit card for pre-paid subscription for your account didn't go through. Please check your credit card or register new credit card for your account and we'll give it another try!",
|
||||
'charge_from_card_failed_action' => 'Go to Billing Settings',
|
||||
'charge_from_card_failed_again_subject' => 'Uh-oh! Your withdrawal from your credit card for pre-paid subscription failed once again',
|
||||
'charge_from_card_failed_again_line' => "It looks like withdrawal from your credit card for pre-paid subscription for your account didn't go through once again. Please check your credit card or register new credit card for your account and we'll give it another try!",
|
||||
'charge_from_card_failed_again_action' => 'Update Your Payment Information',
|
||||
'confirm_payment' => 'Confirm Payment',
|
||||
'confirm_payment_greeting' => 'Confirm your :amount payment',
|
||||
'confirm_payment_line' => 'Extra confirmation is needed to process your payment. Please continue to the payment page by clicking on the button below.',
|
||||
'confirm_payment_action' => 'Confirm Payment',
|
||||
'registration_bonus' => 'Registration Bonus',
|
||||
'number' => 'Number',
|
||||
'head_office' => 'Head Office',
|
||||
'vat_id' => 'VAT ID',
|
||||
'date_of_issue' => 'Date of issue',
|
||||
'period' => 'Period',
|
||||
'Description' => 'description',
|
||||
'description' => 'description',
|
||||
'generated_by' => 'Generated by',
|
||||
'synchronize_plans' => 'Synchronize Plans',
|
||||
'synchronizing_plans' => 'Synchronizing Plans...',
|
||||
'plans_are_synchronizing' => 'Your plans are synchronizing with the payment gateways',
|
||||
'plans_was_synchronized' => 'Plans was successfully synchronized',
|
||||
],
|
||||
'regular' => [
|
||||
'type' => 'Type',
|
||||
'cancel' => 'Cancel',
|
||||
'close' => 'Close',
|
||||
'create_folder' => 'Create folder',
|
||||
'delete' => 'Delete',
|
||||
'download_item' => 'Download item',
|
||||
'info_panel' => 'Info panel',
|
||||
'move' => 'Move',
|
||||
'print' => 'Print item',
|
||||
'share_item' => 'Share item',
|
||||
'sorting_view' => 'Sorting and View',
|
||||
'upload_files' => 'Upload Files',
|
||||
'dashboard' => 'Dashboard',
|
||||
'pages' => 'Pages',
|
||||
'settings' => 'Settings',
|
||||
'users' => 'Users',
|
||||
'license' => 'License',
|
||||
'version' => 'Version',
|
||||
'show_all_users' => 'Show All Users',
|
||||
'change_capacity' => 'Change Capacity',
|
||||
'avatar' => 'Avatar',
|
||||
'account_details' => 'Account Details',
|
||||
'admin_page_user.create_user.label_email' => 'Type E-mail',
|
||||
'admin_page_user.create_user.label_name' => 'Type full name',
|
||||
'admin_page_user.create_user.submit' => 'Create User',
|
||||
'admin_page_user.delete_user' => 'Delete User',
|
||||
'admin_page_user.label_change_capacity' => 'Type storage capacity in GB',
|
||||
'admin_page_user.label_delete_user' => 'Type with Case Sensitive user name ‘{user}‘',
|
||||
'admin_page_user.label_person_info' => 'Personal Information',
|
||||
'admin_page_user.placeholder_delete_user' => 'Type here',
|
||||
'admin_page_user.save_role' => 'Save Role',
|
||||
'admin_page_user.select_role' => 'Select user role',
|
||||
'admin_page_user.send_password_link' => 'Send Password Reset Link',
|
||||
'action' => 'Action',
|
||||
'user' => 'User',
|
||||
'role' => 'Role',
|
||||
'storage_used' => 'Storage Used',
|
||||
'detail' => 'Detail',
|
||||
'password' => 'Password',
|
||||
'content' => 'Content',
|
||||
'admin_pages.form.content_plac' => 'Type your content here...',
|
||||
'slug' => 'Slug',
|
||||
'title' => 'Title',
|
||||
'admin_pages.form.title_plac' => 'Title name',
|
||||
'visibility' => 'Visibility',
|
||||
'admin_pages.form.visibility_help' => 'Status of your page visibility on website.',
|
||||
'page' => 'Page',
|
||||
'status' => 'Status',
|
||||
'admin_settings.appearance.description' => 'App Description',
|
||||
'admin_settings.appearance.description_plac' => 'Type your app description',
|
||||
'admin_settings.appearance.favicon' => 'App Favicon (optional)',
|
||||
'admin_settings.appearance.logo' => 'App Logo (optional)',
|
||||
'app_logo_dark_mode' => 'App Logo Dark Mode (optional)',
|
||||
'app_logo_horizontal_dark_mode' => 'App Logo Horizontal Dark Mode (optional)',
|
||||
'admin_settings.appearance.logo_horizontal' => 'App Logo Horizontal (optional)',
|
||||
'admin_settings.appearance.section_general' => 'General Settings',
|
||||
'admin_settings.appearance.title' => 'App Title',
|
||||
'admin_settings.appearance.title_plac' => 'Type your app title',
|
||||
'admin_settings.email.driver' => 'Mail Driver',
|
||||
'admin_settings.email.email_disclaimer' => "This form is not fully pre-filled for security reasons. Your email settings is available in your <b class='text-theme dark-text-theme'>.env</b> file. For apply new Email settings, please confirm your options by button at the end of formular.",
|
||||
'admin_settings.email.encryption' => 'Mail Encryption',
|
||||
'admin_settings.email.host' => 'Mail Host',
|
||||
'admin_settings.email.password' => 'Mail Password',
|
||||
'admin_settings.email.password_plac' => 'Type your mail password',
|
||||
'admin_settings.email.port' => 'Mail Port',
|
||||
'admin_settings.email.save_button' => 'Save Email Settings',
|
||||
'admin_settings.others.allow_registration' => 'Allow User Registration',
|
||||
'admin_settings.others.allow_registration_help' => 'You can disable public registration for new users. You will still able to create new users in administration panel.',
|
||||
'admin_settings.others.allow_user_verification' => 'Allow User Email Verification',
|
||||
'clear_cache' => 'Clear Cache',
|
||||
'admin_settings.others.contact_email' => 'Contact Email',
|
||||
'admin_settings.others.contact_email_plac' => 'Type your contact email',
|
||||
'admin_settings.others.default_storage' => 'Default Storage Space for User Accounts (in GB)',
|
||||
'admin_settings.others.default_storage_plac' => 'Set default storage space in GB',
|
||||
'admin_settings.others.google_analytics' => 'Google Analytics Code (optional)',
|
||||
'admin_settings.others.google_analytics_plac' => 'Paste your Google Analytics Code',
|
||||
'admin_settings.others.mimetypes_blacklist' => 'Mimetypes Blacklist',
|
||||
'admin_settings.others.mimetypes_blacklist_help' => "If you want to prevent upload some type of files, just add them to blacklist like this: x-php,mp3,jpeg Use a comma between each mimetype. Don't use a dot before mimetypes.",
|
||||
'admin_settings.others.mimetypes_blacklist_plac' => 'Add mimetypes to Blacklist',
|
||||
'admin_settings.others.storage_limit' => 'Storage Limitation',
|
||||
'admin_settings.others.storage_limit_help' => "If this value is off, all users will have infinity storage capacity and you won't be able to charge your users for storage plan.",
|
||||
'admin_settings.others.upload_limit' => 'Upload Limit (in MB)',
|
||||
'admin_settings.others.upload_limit_help' => 'If you want to set max file size limit on single upload, add size of your limit in MB. E.g. 100 means 100 MB and 2 000 means 2 000 MB limit.',
|
||||
'admin_settings.others.upload_limit_plac' => 'Type your upload limit in MB',
|
||||
'appearance' => 'Appearance',
|
||||
'admin_settings.tabs.others' => 'Application',
|
||||
'alerts.error_confirm' => 'That’s horrible!',
|
||||
'alerts.leave_to_sign_in' => 'Do you really want to leave?',
|
||||
'alerts.success_confirm' => 'Awesome!',
|
||||
'add_to_favourites' => 'Add to Favourites',
|
||||
'download' => 'Download',
|
||||
'copy' => 'Copy',
|
||||
'empty_trash' => 'Flush',
|
||||
'remove_favourite' => 'Remove Favourite',
|
||||
'rename' => 'Rename',
|
||||
'restore' => 'Restore',
|
||||
'select' => 'Select',
|
||||
'share' => 'Share',
|
||||
'cancel_sharing' => 'Cancel Sharing',
|
||||
'edit_sharing' => 'Edit Sharing',
|
||||
'upload' => 'Upload',
|
||||
'cookie_disclaimer.button' => 'cookies policy',
|
||||
'cookie_disclaimer.description' => 'By browsing this website you are agreeing to our {0}',
|
||||
'datatable.paginate_info' => 'Showing 1 - {visible} from {total} records',
|
||||
'empty_page.call_to_action' => 'Upload Files',
|
||||
'empty_page.description' => 'Upload some files here easily via upload button.',
|
||||
'empty_page.title' => 'Upload Your First File',
|
||||
'errors.capacity_digit' => 'The storage capacity must be lower than 10 digit number.',
|
||||
'created_at' => 'Created at',
|
||||
'items' => 'Items',
|
||||
'space' => 'space',
|
||||
'selected_multiple' => 'Selected Multiple Items',
|
||||
'shared' => 'Shared',
|
||||
'size' => 'Size',
|
||||
'where' => 'Where',
|
||||
'aperature' => 'F Number',
|
||||
'aperture_value' => 'Aperture Value',
|
||||
'author' => 'Author',
|
||||
'camera_lens' => 'Camera Lens',
|
||||
'color_space' => 'Color Space',
|
||||
'dimension' => 'Dimensions',
|
||||
'exposure' => 'Exposure Time',
|
||||
'focal' => 'Focal Length',
|
||||
'iso' => 'ISO',
|
||||
'latitude' => 'Latitude',
|
||||
'longitude' => 'Longitude',
|
||||
'make' => 'Camera',
|
||||
'meta_data' => 'Metadata',
|
||||
'model' => 'Model',
|
||||
'resolution' => 'Resolution',
|
||||
'time_data' => 'Content Created',
|
||||
'empty' => 'Empty',
|
||||
'folder.item_counts' => '{count} Item | {count} Items',
|
||||
'admin' => 'Admin',
|
||||
'yes_iam_sure' => "Yes, I'm sure",
|
||||
'free' => 'Free',
|
||||
'get_it' => 'Get It',
|
||||
'input_image.supported' => 'Supported formats are .png, .jpg, .jpeg.',
|
||||
'input_image.title' => 'Upload Image',
|
||||
'search_anything' => 'Search anything...',
|
||||
'item_thumbnail.deleted_at' => 'Deleted {time}',
|
||||
'locations.home' => 'Files',
|
||||
'logout' => 'Log Out',
|
||||
'locations.profile' => 'Profile',
|
||||
'locations.settings' => 'Settings',
|
||||
'locations.trash' => 'Trash',
|
||||
'administration' => 'Administration',
|
||||
'menu.files' => 'Files',
|
||||
'menu.latest' => 'Recent Uploads',
|
||||
'menu.password' => 'Security & API',
|
||||
'menu.profile' => 'Profile Settings',
|
||||
'menu.shared' => 'Shared Files',
|
||||
'storage' => 'Storage',
|
||||
'trash' => 'Trash',
|
||||
'nothing_to_preview' => 'There is nothing to preview.',
|
||||
'messages.nothing_was_found' => 'Nothing was found.',
|
||||
'deselect_all' => 'Deselect All',
|
||||
'done' => 'Done',
|
||||
'select_all' => 'Select All',
|
||||
'page_contact_us.description' => 'Do you have any questions? Get in touch with us.',
|
||||
'page_contact_us.error_message' => 'Something went wrong, please try it again.',
|
||||
'page_contact_us.form.email_plac' => 'Type your email',
|
||||
'message' => 'Message',
|
||||
'page_contact_us.form.message_plac' => 'Type your message here...',
|
||||
'send_message' => 'Send Message',
|
||||
'page_contact_us.success_message' => 'Your message was send successfully.',
|
||||
'update_password' => 'Update Password',
|
||||
'confirm_password' => 'Confirm password',
|
||||
'email' => 'Email',
|
||||
'new_password' => 'New password',
|
||||
'page_create_password.subtitle' => 'Create your new password here',
|
||||
'page_create_password.title' => 'Only One Step to Log In',
|
||||
'get_link' => 'Get Link',
|
||||
'sign_in' => 'Sign In',
|
||||
'page_forgotten_password.pass_reseted_subtitle' => 'Your password was reset successfully.',
|
||||
'page_forgotten_password.pass_reseted_title' => 'Awesome!',
|
||||
'page_forgotten_password.pass_sennded_subtitle' => 'We have e-mailed your password reset link!',
|
||||
'page_forgotten_password.pass_sennded_title' => 'Thank you!',
|
||||
'page_forgotten_password.password_remember_text' => 'Remember your password?',
|
||||
'page_forgotten_password.subtitle' => 'Get reset link with your email',
|
||||
'page_forgotten_password.title' => 'Forgotten Password?',
|
||||
'sign_up_now' => 'Sign Up Now',
|
||||
'contact_us' => 'Contact Us',
|
||||
'pricing' => 'Pricing',
|
||||
'page_index.menu.sign_in' => 'Sign Up',
|
||||
'page_index.sign_feature_1' => 'No credit card required',
|
||||
'page_index.sign_feature_2' => '{defaultSpace} Free storage space',
|
||||
'page_index.sign_up_button' => 'Sign Up Now',
|
||||
'next_step' => 'Next Step',
|
||||
'page_login.placeholder_email' => 'Type your E-mail',
|
||||
'page_login.registration_button' => 'Register account.',
|
||||
'page_login.registration_text' => 'Don’t have an account?',
|
||||
'page_login.subtitle' => 'Please type your email to log in',
|
||||
'welcome_back' => 'Welcome Back!',
|
||||
'page_registration.agreement' => "By clicking on 'Create Account' button I agree to the {0} and {1}.",
|
||||
'create_account' => 'Create Account',
|
||||
'page_registration.have_an_account' => 'Do you have an account?',
|
||||
'full_name' => 'Full Name',
|
||||
'page_registration.label_pass' => 'Create password',
|
||||
'page_registration.placeholder_confirm_pass' => 'Confirm your new password',
|
||||
'page_registration.placeholder_email' => 'Type your E-mail',
|
||||
'page_registration.placeholder_name' => 'Type your full name',
|
||||
'page_registration.subtitle' => 'Please fill registration to create account',
|
||||
'page_registration.title' => 'Create New Account',
|
||||
'page_shared.download_file' => 'Download File',
|
||||
'page_shared.placeholder_pass' => 'Type password',
|
||||
'submit' => 'Submit',
|
||||
'page_shared.subtitle' => 'Please type the password to get shared content',
|
||||
'page_shared.title' => 'Your Share Link is Protected',
|
||||
'page_shared_404.subtitle' => 'The content you are finding was probably deleted.',
|
||||
'page_shared_404.title' => 'Not Found :(',
|
||||
'log_in' => 'Log In',
|
||||
'page_sign_in.password_reset_button' => 'Reset Password.',
|
||||
'page_sign_in.password_reset_text' => 'Forgotten your password?',
|
||||
'page_sign_in.placeholder_password' => 'Type your password',
|
||||
'page_sign_in.subtitle' => 'Confirm you by your password',
|
||||
'page_sign_in.title' => 'Are You {name}?',
|
||||
'page_sign_in_2fa_title' => 'Welcome {name}',
|
||||
'page_sign_in_2fa_subtitle' => 'Confirm you by 2FA code from your Authenticator app',
|
||||
'page_sign_in.placeholder_2fa' => 'Type your 2FA code...',
|
||||
'page_sign_in.2fa_recovery_text' => "Can't get your 2FA code?",
|
||||
'page_sign_in.2fa_recovery_button' => 'Use recovery code.',
|
||||
'page_sign_in.2fa_recovery_subtitle' => 'Use your recovery code',
|
||||
'page_sign_in.placeholder_2fa_recovery' => 'Type your recovery code',
|
||||
'page_not_verified.subtitle' => 'Your account is not verified. Before login, verify your account please.',
|
||||
'page_not_verified.resend_text' => 'Do you want resend verification email?',
|
||||
'page_not_verified.resend_button' => 'Resend verification email.',
|
||||
'page_email_successfully_verified.title' => 'Your account was successfully verified!',
|
||||
'page_email_successfully_verified.subtitle' => 'Now you can log in.',
|
||||
'page_email_successfully_send.title' => 'Verification email was successfully send!',
|
||||
'page_email_successfully_send.subtitle' => 'Check your email address where the email was send.',
|
||||
'popup_create_folder.folder_default_name' => 'New Folder',
|
||||
'popup_create_folder.label' => 'Type Name',
|
||||
'popup_create_folder.placeholder' => 'Type your name',
|
||||
'popup_create_folder.title' => 'Create Folder',
|
||||
'popup_deleted_user.message' => 'Your user was deleted with all user data content.',
|
||||
'popup_deleted_user.title' => 'User was deleted',
|
||||
'popup_deleted_user_aborted.message' => "You can't delete this account while user have active subscription.",
|
||||
'popup_deleted_user_aborted.title' => "User wasn't deleted",
|
||||
'popup_error.message' => "Something went wrong and we can't continue. Please contact us.",
|
||||
'popup_error.title' => 'Whooops, something went wrong!',
|
||||
'popup_exceed_limit.message' => 'Please upgrade your account to change your limit.',
|
||||
'popup_exceed_limit.title' => 'You exceed storage limit',
|
||||
'popup_mimetypes_blacklist.message' => 'File of this type ({mimetype}) is not allowed to upload.',
|
||||
'popup_mimetypes_blacklist.title' => 'You are trying to upload unsupported file type',
|
||||
'popup_move_item.submit' => 'Move Item',
|
||||
'popup_move_item.title' => 'Move Item',
|
||||
'popup_pass_changed.message' => 'So now, you have awesome new password.',
|
||||
'popup_pass_changed.title' => 'Your password was changed!',
|
||||
'popup_paylod_error.message' => "Sorry, your file is too large and can't be uploaded",
|
||||
'popup_paylod_error.title' => 'File is too large',
|
||||
'popup_rename.select_emoji_label' => 'Pick Your Emoji Icon',
|
||||
'popup_rename.label' => 'Edit Name',
|
||||
'popup_rename.placeholder' => 'Type your title',
|
||||
'popup_rename.title' => 'Rename Your {item}',
|
||||
'popup_share_create.title' => 'Share Your {item}',
|
||||
'popup_share_edit.change_pass' => 'Change Password',
|
||||
'popup_share_edit.confirm' => 'Confirm',
|
||||
'popup_share_edit.save' => 'Save Changes',
|
||||
'popup_share_edit.stop' => 'Cancel Sharing',
|
||||
'popup_share_edit.title' => 'Update sharing options',
|
||||
'popup_signup_error.message' => 'Please check your database connection if everything works correctly.',
|
||||
'popup_signup_error.title' => 'Server Error',
|
||||
'popup_upload_limit.message' => 'Size of your uploaded file exceed the upload limit ({uploadLimit}).',
|
||||
'popup_upload_limit.title' => 'You exceed upload limit on single file',
|
||||
'preview_sorting.grid_view' => 'Grid View',
|
||||
'preview_sorting.list_view' => 'List View',
|
||||
'preview_sorting.preview_sorting_button' => 'View',
|
||||
'preview_sorting.sort_alphabet' => 'Sort By Aplhabet',
|
||||
'preview_sorting.sort_date' => 'Sort By Date',
|
||||
'profile.store_pass' => 'Store New Password',
|
||||
'pronouns.of' => 'of',
|
||||
'roles.admin' => 'Admin',
|
||||
'roles.user' => 'User',
|
||||
'others' => 'Others',
|
||||
'edit_page' => 'Edit Page',
|
||||
'my_profile' => 'My Profile',
|
||||
'change_password' => 'Security & API',
|
||||
'create_user' => 'Create User',
|
||||
'delete_user' => 'Delete User',
|
||||
'routes_title.users_list' => 'User Management',
|
||||
'routes_title.users_password' => 'Password',
|
||||
'routes_title.users_storage_usage' => 'Storage Usage',
|
||||
'routes_title.users_user' => 'User',
|
||||
'can_download_file' => 'Can download file',
|
||||
'shared.editor' => 'Can edit and upload files',
|
||||
'shared.empty_shared' => 'Nothing Shared Yet',
|
||||
'shared.empty_shared_desc' => 'All items you share will be visible here.',
|
||||
'shared.visitor' => 'Can only view and download',
|
||||
'awesome_iam_done' => 'Awesome, I’m done!',
|
||||
'generate_link' => 'Generate Link',
|
||||
'shared_form.email_placeholder' => 'Type your emails',
|
||||
'shared_form.expiration_day' => '{value}d.',
|
||||
'shared_form.expiration_hour' => '{value}h.',
|
||||
'password_protected' => 'Password Protected',
|
||||
'permission' => 'Permission',
|
||||
'shared_form.label_send_to_recipients' => 'Send to Recipients',
|
||||
'get_your_link' => 'Get your link',
|
||||
'shared_form.placeholder_permission' => 'Select your permission',
|
||||
'recipients' => 'Recipients',
|
||||
'favourites' => 'Favourites',
|
||||
'sidebar.favourites_empty' => 'Drag here your favourite folder.',
|
||||
'sidebar.home' => 'My Files',
|
||||
'sidebar.latest' => 'Recent Uploads',
|
||||
'sidebar.locations_title' => 'Base',
|
||||
'publicly_shared' => 'Publicly Shared',
|
||||
'navigator' => 'Navigator',
|
||||
'toaster.changed_capacity' => "You successfully changed user's storage size!",
|
||||
'toaster.changed_user' => "You successfully changed user's role!",
|
||||
'toaster.created_user' => 'User was created successfully!',
|
||||
'toaster.email_set' => 'Your email settings was updated successfully',
|
||||
'toaster.sended_password' => 'You successfully send user email for reset password!',
|
||||
'file' => 'File',
|
||||
'folder' => 'Folder',
|
||||
'uploading.cancel' => 'Cancel Uploading',
|
||||
'uploading.processing_file' => 'Processing File...',
|
||||
'uploading.progress' => 'Uploading File {progress}% - {current}/{total}',
|
||||
'user_box_delete.description' => 'You can delete your user, but, pay attention! This event is irreversible and all user data include user files will be deleted.',
|
||||
'user_box_delete.title' => 'Delete User',
|
||||
'user_box_password.description' => 'You can send password reset email via button bellow. User will be redirected to page where he can update password for his account.',
|
||||
'user_box_password.title' => 'Change User Password',
|
||||
'user_box_role.description' => 'You can change role for current user. Admin role can edit or create new users, change storage capacity and any other application settings.',
|
||||
'user_box_role.title' => 'Change User Role',
|
||||
'user_box_storage.description' => "Change user storage capacity by input above. You have to type only number e.g. value '5' means, user will have 5GB of storage capacity.",
|
||||
'user_box_storage.title' => 'Change User Storage Capacity',
|
||||
'user_password.title' => 'Change Your Password',
|
||||
'address' => 'Address',
|
||||
'user_settings.address_plac' => 'Type your billing address',
|
||||
'city' => 'City',
|
||||
'user_settings.city_plac' => 'Type your billing city',
|
||||
'country' => 'Country',
|
||||
'user_settings.country_plac' => 'Select your billing country',
|
||||
'name' => 'Name',
|
||||
'user_settings.name_plac' => 'Type your billing name',
|
||||
'phone_number' => 'Phone Number',
|
||||
'user_settings.phone_number_plac' => 'Type your billing phone number',
|
||||
'postal_code' => 'Postal Code',
|
||||
'postal_code_plac' => 'Type your postal code',
|
||||
'state' => 'State',
|
||||
'user_settings.state_plac' => 'Type your billing state',
|
||||
'timezone' => 'Timezone',
|
||||
'select_your_timezone' => 'Select your timezone',
|
||||
'account_information' => 'Account Information',
|
||||
'billing_information' => 'Billing Information',
|
||||
'validation_errors.incorrect_2fa_code' => 'Sorry, you passed incorrect or expired code',
|
||||
'validation_errors.incorrect_2fa_recovery_code' => 'Sorry, you passed incorrect recovery code',
|
||||
'validation_errors.incorrect_password' => 'Sorry, you passed incorrect password :(',
|
||||
'wrong_image_error' => 'You may have uploaded the wrong file, try again!',
|
||||
'app_description' => 'Your self-hosted storage cloud software powered by Laravel and Vue',
|
||||
'user_not_fount' => 'We can\'t find a user with that e-mail address.',
|
||||
'incorrect_password' => 'Sorry, your password is incorrect.',
|
||||
'time' => 'd. M. Y, h:i',
|
||||
'home' => 'Home',
|
||||
'shared_link_email_subject' => '🙋 :user share some files with you. Look at it!',
|
||||
'shared_link_email_user' => ':user (:email) send you a link to shared files.',
|
||||
'shared_link_email_link' => 'Open your files',
|
||||
'shared_link_email_salutation' => 'Regards, :app_name',
|
||||
'hello' => 'Hello!',
|
||||
'reset_password_subject' => 'Reset password for your account on ',
|
||||
'reset_password_line_1' => 'You are receiving this email because we received a password reset request for your account.',
|
||||
'reset_password_line_2' => 'If you did not request a password reset, no further action is required.',
|
||||
'reset_password' => 'Reset Password',
|
||||
'salutation' => 'Regards',
|
||||
'user_sending' => ':name is sending you this file',
|
||||
'protected_file' => 'This link is protected by password',
|
||||
'languages' => 'Languages',
|
||||
'add_language' => 'Add Language',
|
||||
'create_language' => 'Create Language',
|
||||
'edit_translations' => 'Edit Translations',
|
||||
'language_name' => 'Language Name',
|
||||
'set_as_default_language' => 'Set as Default Language',
|
||||
'language_settings' => 'Language Settings',
|
||||
'search_translations' => 'Search Language Translations...',
|
||||
'select_locale' => 'Select Locale',
|
||||
'locale_name' => 'Language Name',
|
||||
'select_language_locale' => 'Select Language Locale',
|
||||
'type_language_name' => 'Type Language Name',
|
||||
'go_to_files' => 'Go to Files',
|
||||
'color_theme' => 'Color Theme',
|
||||
'color_theme_description' => 'Your color change will be visible after app refresh.',
|
||||
'og_image' => 'OG Image',
|
||||
'og_image_description' => 'Image that appear when someone shares the content to Facebook or any other social medium. Preferred size is 1200x627',
|
||||
'app_touch_icon' => 'App Touch Icon',
|
||||
'app_touch_icon_description' => 'If user store bookmark on his phone screen, this icon appear in app thumbnail. Preferred size is 156x156',
|
||||
'search_in_list' => 'Search in list...',
|
||||
'2fa.settings.title' => 'Two Factor Authentication',
|
||||
'2fa.i_have_2fa_app' => 'I have already 2FA app',
|
||||
'confirm_your_password' => 'Confirm Your Password',
|
||||
'popup_2fa.help' => 'Scan the image above with the <b class="text-theme dark-text-theme">two-factor authentication app</b> on your phone.',
|
||||
'confirm' => 'Confirm',
|
||||
'popup_2fa.toaster_enabled' => 'Your 2FA was enabled successfully!',
|
||||
'popup_2fa.toaster_disabled' => 'Your 2FA was disabled!',
|
||||
'popup_2fa.switch_title' => 'Enable / Disable Two Factor Authentication',
|
||||
'popup_2fa.switch_info' => 'Here you can improve your account security by turn on 2fa verification.',
|
||||
'show_recovery_codes' => 'Show Recovery Codes',
|
||||
'popup_2fa.codes_info' => 'Recovery codes can be used to access your account in the event you lose access to your device and cannot receive two-factor authentication codes.',
|
||||
'show_codes' => 'Show Codes',
|
||||
'your_security_codes' => 'Your Security Codes',
|
||||
'popup_2fa.popup_codes_disclaimer' => '<b class="text-theme dark-text-theme">Put these in a safe spot.</b> If you lose your device and don’t have the recovery codes you will lose access to your account.',
|
||||
'regenerate_codes' => 'Regenerate Codes',
|
||||
'popup_2fa.toaster_codes_copied' => 'Your codes was copied!',
|
||||
'popup_2fa.toaster_codes_regenerated' => 'Your codes was regenerated!',
|
||||
'go_home' => 'Go to the homepage',
|
||||
'never' => 'Never',
|
||||
'last_used' => 'Last Used',
|
||||
'personal_access_token' => 'Personal Access Token',
|
||||
'personal_token.section_description' => "You don't have any created personal access tokens yet.",
|
||||
'create_token' => 'Create Token',
|
||||
'create_personal_token' => 'Create Personal Token',
|
||||
'token_name' => 'Token Name',
|
||||
'popup_personal_token.plc' => 'Type token name...',
|
||||
'popup_personal_token.your_token' => 'Your Personal Access Token',
|
||||
'popup_personal_token.copy_token' => "Make sure to <b class='text-theme dark-text-theme'>copy your personal access token now</b>. You won’t be able to see it again!",
|
||||
'popup_delete_personal_token.title' => 'Are you sure you want to delete this token?',
|
||||
'popup_delete_personal_token.description' => 'Any applications or scripts using this token will no longer be able to access into your account. You cannot undo this action.',
|
||||
'personal_token.token_deleted' => 'Token was successfully deleted!',
|
||||
'dark_mode_toggle' => 'Toggle Dark Mode',
|
||||
'convert_into_team_folder' => 'Convert into Team Folder',
|
||||
'create_something' => 'Create Something',
|
||||
'popup.share.email_send' => 'Send link by Email',
|
||||
'popup.share.email_description' => 'Send your share link via email to many recipients.',
|
||||
'expiration' => 'Expiration',
|
||||
'popup.share.expiration_description' => 'Your link expire after exact period of time.',
|
||||
'popup.share.password_description' => 'Protect your item by your custom password.',
|
||||
'sharelink.share_via_email' => 'Share Link on Emails',
|
||||
'sharelink.copy_embed' => 'Copy Web Insert Code',
|
||||
'popup.move_into_team_disclaimer' => 'Your folder <b class="text-theme dark-text-theme">will be moved</b> into Team Folders section.',
|
||||
'upload_folder' => 'Upload Folder',
|
||||
'member' => 'Members',
|
||||
'request_for_upload' => '{name} is Asking You For Files',
|
||||
'upload_request' => 'Upload Request',
|
||||
'request_for_upload_success' => 'Upload Request for {name} was Fulfilled Successfully',
|
||||
'request_for_upload_expired' => 'Upload Request Expired',
|
||||
'automatically_uploads_for_file_request' => 'Your files will be uploaded automatically and after that, you can organize your files in folders.',
|
||||
'request_for_upload_unavailable' => 'This upload request is no longer available for uploading files.',
|
||||
'closing_request_for_upload' => 'Are you sure you uploaded all files you want for {name}?',
|
||||
'closing_request_for_upload_warn' => "You won't be able to upload any files here once again.",
|
||||
'user_leave_message' => '{name} leave you a message',
|
||||
'tell_you_are_done' => 'Tell {name} you are done!',
|
||||
'user_invite_you_into_team_folder' => '{name} invite you to join with his team into shared team folder',
|
||||
'register_with_email_and_get_folder' => 'Register account with your email {email} and get access to this Team Folder.',
|
||||
'invite_to_join_team_folder' => 'Invitation To Join Team Folder',
|
||||
'or_decline_your_invitation' => 'Or {0} your invitation.',
|
||||
'decline' => 'Decline',
|
||||
'you_are_successfully_joined' => 'You are successfully joined',
|
||||
'proceed_to_participate_with_team' => 'You can now proceed to your account and participate in team folder',
|
||||
'proceed_to_your_account' => 'Proceed to your account',
|
||||
'go_to_team_folder' => 'Go to Team Folder',
|
||||
'you_denied_invitation' => 'You are successfully denied invitation',
|
||||
'invitation_used' => 'Your invitation has been used',
|
||||
'invitation_used_description' => 'We are sorry but this invitation was used previously',
|
||||
'go_to_your_shared_folders' => 'Go to your shared folders',
|
||||
'accept_invitation' => 'Accept Invitation',
|
||||
'accept_and_register' => 'Accept and Register Account',
|
||||
'application' => 'Application',
|
||||
'account_settings' => 'Account Settings',
|
||||
'first_name' => 'First Name',
|
||||
'last_name' => 'Last Name',
|
||||
'gmt' => 'GMT',
|
||||
'theme_mode' => 'Theme Mode',
|
||||
'set_default_theme_disclaimer' => 'Set your theme mode on dark, light or based on your system settings.',
|
||||
'default_emojis' => 'Default Emojis',
|
||||
'set_default_emoji_disclaimer' => 'Set your default emojis for your folder custom icons. You can set Twemoji or default Apple emojis.',
|
||||
'light_mode' => 'Light mode',
|
||||
'dark_mode' => 'Dark mode',
|
||||
'based_on_system' => 'Based on system settings',
|
||||
'storage_usage' => 'Storage Usage',
|
||||
'total_of' => 'Total of {capacity}',
|
||||
'used' => 'Used',
|
||||
'in_last_x_days' => 'In last 45 days',
|
||||
'edit_members' => 'Edit Members',
|
||||
'dissolve_team' => 'Dissolve Team',
|
||||
'edit_team_members' => 'Edit Team Members',
|
||||
'file_request' => 'File Request',
|
||||
'create_team_folder_description' => 'Collaborate on your files with your team easily by creating new team folder.',
|
||||
'create_team_folder' => 'Create Team Folder',
|
||||
'spotlight' => 'Spotlight',
|
||||
'your_trash_is_empty' => 'Your Trash is Empty',
|
||||
'your_trash_is_empty_desc' => 'After you delete the files, you can restore them from trash.',
|
||||
'create' => 'Create',
|
||||
'upload_or_create' => 'Upload / Create',
|
||||
'base' => 'Base',
|
||||
'not_any_folder' => "There isn't any folder.",
|
||||
'collaboration' => 'Collaboration',
|
||||
'team_folders' => 'Team Folders',
|
||||
'shared_with_me' => 'Shared with Me',
|
||||
'broadcasting' => 'Broadcasting',
|
||||
'view' => 'View',
|
||||
'sorting' => 'Sorting',
|
||||
'accept' => 'Accept',
|
||||
'you_accepted_invitation' => 'You successfully accepted invitation',
|
||||
'you_decline_invitation' => 'You successfully decline invitation',
|
||||
'notification_center' => 'Notification Center',
|
||||
'clear_all' => 'Clear all',
|
||||
'not_any_notifications' => "There aren't any notifications.",
|
||||
'unread' => 'Unread',
|
||||
'read' => 'Read',
|
||||
'notifications' => 'Notifications',
|
||||
'options' => 'Options',
|
||||
'loading_content' => 'loading content...',
|
||||
'note' => 'Note',
|
||||
'user_was_deleted' => 'User was deleted',
|
||||
'max_storage' => 'Max Storage',
|
||||
'create_file_request' => 'Create File Request',
|
||||
'convert_as_team_folder' => 'Convert as Team Folder',
|
||||
'leave_team_folder' => 'Leave the Team Folder',
|
||||
'nothing_shared_with_you' => 'Nothing Shared With You',
|
||||
'nothing_shared_with_you_description' => 'All items that are shared with you will be visible here.',
|
||||
'you_left_team_folder' => 'You have successfully left the team folder',
|
||||
'there_is_nothing' => 'There is Nothing',
|
||||
'frequently_used' => 'Frequently Used',
|
||||
'there_is_nothing_smile' => 'There is nothing :(',
|
||||
'cache' => 'Cache',
|
||||
'cache_note' => 'Did you change anything in your .env file? Then clear your cache.',
|
||||
'there_is_not_log' => 'There is not any server log.',
|
||||
'there_is_not_database_backup' => 'There is not any database backup stored.',
|
||||
'backup_path' => 'You can find your backups in <b>/storage/app/app-backups</b>.',
|
||||
'update_your_credentials' => 'Update Your Credentials',
|
||||
'search_your_users' => 'Search through your users...',
|
||||
'files_and_folders' => 'Files & Folders',
|
||||
'actions' => 'Actions',
|
||||
'suggested_filters' => 'Suggested Filters',
|
||||
'go' => 'Go',
|
||||
'navigate' => 'Navigate',
|
||||
'web_code_copied' => 'Your web insert code was copied',
|
||||
'share_with_multiple_emails' => 'Share on multiple emails',
|
||||
'get_qr_code' => 'Get your QR code',
|
||||
'store_changes' => 'Store Changes',
|
||||
'send' => 'Send',
|
||||
'show_details' => 'Show Details',
|
||||
'select_or_search_emoji' => 'Select or search emoji icon...',
|
||||
'create_request' => 'Create Request',
|
||||
'copy_upload_request_link' => 'Copy your upload request link',
|
||||
'type_email_' => 'Type email...',
|
||||
'send_request_by_email' => 'Send Request by Email',
|
||||
'send_request_by_email_description' => 'Send your file request on recipients email',
|
||||
'message_for_recipient' => 'Type message for recipient...',
|
||||
'message_optional' => 'Message (optional)',
|
||||
'message_optional_description' => 'This message will be showed for your email recipient or in the upload page.',
|
||||
'folder_name_optional' => 'Folder Name (optional)',
|
||||
'folder_name_optional_description' => 'Created folder with files will be named with your own name.',
|
||||
'type_name_' => 'Type name...',
|
||||
'replace_icon_with_emoji' => 'Replace folder icon with an Emoji',
|
||||
'emoji_as_an_icon' => 'Emoji as an Icon',
|
||||
'current_password' => 'Current Password',
|
||||
'delete_account' => 'Delete Account',
|
||||
'details' => 'Details',
|
||||
'store_credentials' => 'Store Credentials',
|
||||
'default_language_disclaimer' => 'If this language is set as default, app will appear in this language for all users.',
|
||||
'reset_user_password' => 'Reset User Password',
|
||||
'server' => 'Server',
|
||||
'environment' => 'Environment',
|
||||
'homepage' => 'Homepage',
|
||||
'allow_homepage' => 'Allow Homepage',
|
||||
'allow_homepage_note' => 'When this is turned on, your visitors can visit your default homepage.',
|
||||
'storage_upload' => 'Storage & Upload',
|
||||
'allow_recaptcha' => 'Allow ReCaptcha v3',
|
||||
'allow_recaptcha_note' => 'ReCaptcha will be allowed on Registration and Contact Us forms.',
|
||||
'login_and_registration' => 'Login & Registration',
|
||||
'account' => 'Account',
|
||||
'search' => 'Search',
|
||||
'latest_registrations' => 'Latest Registrations',
|
||||
'total_storage' => 'Total Storage',
|
||||
'total_users' => 'Total Users',
|
||||
'temporary_unavailable' => 'Temporary Unavailable',
|
||||
'shared_link_temporary_unavailable' => 'Unfortunately, this shared link is temporary unavailable. Please try it later.',
|
||||
'not_selected' => 'Not selected',
|
||||
'waiting_for_accept_invitation' => 'Waiting for accept invitation...',
|
||||
'team_folder_updated' => 'Your team folder was updated',
|
||||
'update_team_folder' => 'Update Team Folder',
|
||||
'edit_team_folder' => 'Edit Team Folder',
|
||||
'upgrade_to_invite_members' => 'You have to upgrade your account to add this new member.',
|
||||
'type_valid_email' => 'You have to type valid email',
|
||||
'team_was_invited' => 'Your Team was invited successfully.',
|
||||
'team_was_invited_and_folder_moved' => 'Your Team was invited and folder was moved into Team Folders section.',
|
||||
'move_and_invite_members' => 'Move & Invite Members',
|
||||
'add_at_least_one_member' => 'Please add at least one member.',
|
||||
'add_at_least_one_member_into_team_folder' => 'Please add at least one member into your Team Folders.',
|
||||
'your_members' => 'Your Members',
|
||||
'type_member_email_' => 'Type member email...',
|
||||
'add_member' => 'Add Member',
|
||||
'go_to_dashboard' => 'Go To Dashboard',
|
||||
'go_to_settings' => 'Go To Settings',
|
||||
'go_to_payments' => 'Payments / Settings',
|
||||
'go_to_pages' => 'Go To Pages',
|
||||
'go_to_languages' => 'Go To Languages',
|
||||
'show_all_plans' => 'Show all Plans',
|
||||
'show_transactions' => 'Show Transactions',
|
||||
'go_home_spotlight' => 'Go Home',
|
||||
'go_to_recent_uploads' => 'Go To Recent Uploads',
|
||||
'go_to_publicly_shared' => 'Go To Publicly Shared',
|
||||
'go_to_trash' => 'Go To Trash',
|
||||
'go_to_team_folders' => 'Go To Team Folders',
|
||||
'go_to_shared_with_me' => 'Go To Shared with Me',
|
||||
'update_profile_settings' => 'Update Profile Settings',
|
||||
'update_security_api' => 'Update Security & API',
|
||||
'show_storage_details' => 'Show Storage Details',
|
||||
'empty_your_trash' => 'Empty Your Trash',
|
||||
'toggle_grid_list_view' => 'Toggle Grid/List View',
|
||||
'toggle_dark_light_mode' => 'Toggle Dark/Light Mode',
|
||||
'toggle_full_screen_mode' => 'Toggle Full-Screen Mode',
|
||||
'toggle_emoji_type' => 'Toggle Emoji Type',
|
||||
'show_all_subscriptions' => 'Show all Subscriptions',
|
||||
'write_feedback' => 'Write a Feedback',
|
||||
'branding' => 'Branding',
|
||||
'save_broadcast_settings' => 'Save Broadcast Settings',
|
||||
'save_storage_settings' => 'Save Storage Settings',
|
||||
'storage_driver' => 'Storage Driver',
|
||||
'mail_driver' => 'Mail Driver',
|
||||
'select_mail_driver' => 'Select your mail driver',
|
||||
'broadcast_driver_updated' => 'Your broadcast driver was updated.',
|
||||
'storage_driver_updated' => 'Your storage driver was updated.',
|
||||
'spotlight_search' => 'Spotlight search...',
|
||||
'add' => 'Add',
|
||||
'can_edit' => 'Can Edit',
|
||||
'can_view' => 'Can View',
|
||||
'exceed_upload_limit' => 'You exceeded your upload limit',
|
||||
'exceed_upload_limit_description' => 'Unfortunately, you can not upload your file.',
|
||||
'really_dissolve_team' => 'Are you sure you want to dissolve this team?',
|
||||
'really_dissolve_team_desc' => 'All team members will lose access to your files and existing folder will be moved into your "Files" section.',
|
||||
'really_leave_team' => 'Are you sure you want to leave this team folder?',
|
||||
'really_leave_team_desc' => "You will don't have access to the files and all your previously uploaded content will be part of this Team Folder you are leaving.",
|
||||
'images' => 'Images',
|
||||
'videos' => 'Videos',
|
||||
'audios' => 'Audios',
|
||||
'documents' => 'Documents',
|
||||
'paginator' => 'Showing {from} - {to} from {total} records',
|
||||
'require_email_verification' => 'Require Verify Email Address',
|
||||
'require_email_verification_note' => 'Turn on, if you want verify user email address after registration.',
|
||||
'completed' => 'Completed',
|
||||
'error' => 'Error',
|
||||
'cancelled' => 'Cancelled',
|
||||
'active' => 'Active',
|
||||
'archived' => 'Archived',
|
||||
'inactive' => 'Inactive',
|
||||
'total_x_of_x_used' => 'Total {use} of {total} Used',
|
||||
'total_x_of_x_members' => 'Total {use} of {total} Members',
|
||||
'go_back_from_x' => 'Go back from {location}',
|
||||
'new_team_invitation' => 'New Team Invitation',
|
||||
'x_invite_to_join_team' => ':name invite you to join into Team Folder.',
|
||||
'team_invitation_notify_title' => 'You are invited to collaboration with team folder in :app',
|
||||
'team_invitation_notify_desc' => 'You are invited to collaboration with team folder.',
|
||||
'team_invitation_notify_desc_without_account' => 'You are invited to collaboration with team folder. But at first, you have to create an account to proceed into team folder.',
|
||||
'join_into_team_folder' => 'Join into Team Folder',
|
||||
'join_and_create_account' => 'Join & Create an Account',
|
||||
'file_request_filled' => 'File Request Filled',
|
||||
'file_request_filled_desc' => "Your file request for ':name' folder was filled successfully.",
|
||||
'show_files' => 'Show Files',
|
||||
'file_request_filled_mail' => "Your file request was fulfilled in your ':name' folder",
|
||||
'file_request_filled_mail_note' => 'We are emailing you because your file request was fulfilled. Please click on the link below to show uploaded files.',
|
||||
'thanks_salutation' => 'Thank you for using our application!',
|
||||
'upload_your_files' => 'Upload your Files',
|
||||
'file_request_optional_message' => 'PS: :name left you a message: :notes',
|
||||
'file_request_notify_title' => ':name Request You for File Upload',
|
||||
'file_request_notify_description' => 'We are emailing you because :name requested files from you. Please click on the link below and upload your files for :name.',
|
||||
'user_action_not_allowed' => 'This user action is not allowed.',
|
||||
'pcs.' => 'Pcs.',
|
||||
'mem.' => 'Mem.',
|
||||
'password_doesnt_match' => 'The provided password does not match your current password.',
|
||||
'amount' => 'Amount',
|
||||
'upload_request_default_folder' => 'Upload Request from :timestamp',
|
||||
'copy_direct_download_link' => 'Copy Direct Download Link',
|
||||
'direct_link_copied' => 'Your direct download link was copied',
|
||||
'application_settings' => 'Application / Settings',
|
||||
'login_registration_settings' => 'Login & Registration / Settings',
|
||||
'appearance_settings' => 'Appearance / Settings',
|
||||
'adsense_settings' => 'Adsense / Settings',
|
||||
'homepage_settings' => 'Homepage / Settings',
|
||||
'environment_settings' => 'Environment / Settings',
|
||||
'server_settings' => 'Server / Settings',
|
||||
'user_features' => 'User Features',
|
||||
'upload_settings' => 'Upload Settings',
|
||||
'set_up_2fa_app' => 'Set up Your Authenticator App',
|
||||
'confirm_your_code' => 'Confirm Your Code',
|
||||
'paste_code_from_2fa_app' => 'Paste the latest code from 2fa app...',
|
||||
'zero_for_unlimited_members' => 'Type -1 to set unlimited team members.',
|
||||
'max_team_members' => 'Max Team Members',
|
||||
'remote_upload' => 'Remote Upload',
|
||||
'upload_files_remotely' => 'Upload Files Remotely',
|
||||
'remote_links' => 'Remote Links',
|
||||
'remote_links_help' => 'For every new line paste one link and we will give a try to download the file.',
|
||||
'paste_remote_links_here' => 'Paste your links to the files here...',
|
||||
'remote_download_finished' => 'Remote upload was successfully finished',
|
||||
'remote_upload_progress' => 'Uploading Remotely - {processed} / {total}',
|
||||
'remote_upload_failed_count' => 'Failed: {count}',
|
||||
'file_request_notify_center_description' => 'Please click on the link below and upload your files for :name.',
|
||||
],
|
||||
];
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user