mirror of
https://github.com/VueFileManager/vuefilemanager.git
synced 2026-04-06 18:53:48 +00:00
Compare commits
1594 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ba4bf3478 | ||
|
|
640ae2e840 | ||
|
|
29c88eb858 | ||
|
|
9a41720fdf | ||
|
|
517445875d | ||
|
|
519ab53b13 | ||
|
|
6956aa4209 | ||
|
|
16c923bab2 | ||
|
|
bf580f0b55 | ||
|
|
60cdcff4ff | ||
|
|
88fa5732d3 | ||
|
|
b029bfd39a | ||
|
|
5505006d1b | ||
|
|
7db1c7926f | ||
|
|
d1ecd33838 | ||
|
|
49abb58776 | ||
|
|
d8f1f57b89 | ||
|
|
dba177d7f3 | ||
|
|
46971e0765 | ||
|
|
c9e1fcbd3c | ||
|
|
f87fef13cd | ||
|
|
1bc3164a5d | ||
|
|
c323677cfa | ||
|
|
bc5300ad6d | ||
|
|
04b965fd83 | ||
|
|
42ccd553d6 | ||
|
|
b79184bee1 | ||
|
|
751cc6db1b | ||
|
|
245bef8d10 | ||
|
|
132bf23a7e | ||
|
|
ab970ef056 | ||
|
|
b8e97b62c1 | ||
|
|
829e4ec789 | ||
|
|
4c52b6a627 | ||
|
|
e01fc99ef4 | ||
|
|
1ba96f0c43 | ||
|
|
b6c603a97b | ||
|
|
45844f26d3 | ||
|
|
7b4cb694f3 | ||
|
|
8bc046fc73 | ||
|
|
ec5ed24eaa | ||
|
|
22e096cf24 | ||
|
|
f2f18f3063 | ||
|
|
4cafb726df | ||
|
|
e274088b71 | ||
|
|
178a8606b9 | ||
|
|
a26684df79 | ||
|
|
42390af2d5 | ||
|
|
06ee3faa1e | ||
|
|
74898d007f | ||
|
|
ba1fb5aa0b | ||
|
|
afe0a21a29 | ||
|
|
7983195223 | ||
|
|
13d0a5feba | ||
|
|
7fff722377 | ||
|
|
e412f3b88b | ||
|
|
0485672a47 | ||
|
|
ca89117c77 | ||
|
|
2ad5e66831 | ||
|
|
df3303b527 | ||
|
|
aedd6d9120 | ||
|
|
ad02c87f19 | ||
|
|
c9c7a730f6 | ||
|
|
c7ccecf447 | ||
|
|
a4bdb74951 | ||
|
|
dedbc85e57 | ||
|
|
aaea435eb0 | ||
|
|
cd912945cf | ||
|
|
447535bd26 | ||
|
|
38854be63c | ||
|
|
8ec2d5402b | ||
|
|
a61d8434be | ||
|
|
918c0a6fe9 | ||
|
|
ebf1b16aa5 | ||
|
|
119780317d | ||
|
|
9bc8a9b27c | ||
|
|
f3bfe9a0cc | ||
|
|
40b746fb78 | ||
|
|
8a943747eb | ||
|
|
59e3f55ac3 | ||
|
|
16db8d3512 | ||
|
|
d521b237a3 | ||
|
|
3077ec18d1 | ||
|
|
8b5b9c3310 | ||
|
|
c4d7fa1e9b | ||
|
|
96afda9f7c | ||
|
|
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 | ||
|
|
aac0aa755f | ||
|
|
4be77c07ac | ||
|
|
9372906a3e | ||
|
|
e12e521622 | ||
|
|
0082c3a6a8 | ||
|
|
f79973e922 | ||
|
|
59ca45e9b1 | ||
|
|
bb22ec1e88 | ||
|
|
ba315014fa | ||
|
|
8387f56048 | ||
|
|
68acf5f986 | ||
|
|
785dade6b2 |
1
.cursorignore
Normal file
1
.cursorignore
Normal file
@@ -0,0 +1 @@
|
||||
/public
|
||||
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:4CEIUCFnsdvoYgbeG64XjFPZN5WWlblOZsgeIVtwRC8=
|
||||
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="15120"
|
||||
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
|
||||
457
README.md
457
README.md
@@ -1,64 +1,53 @@
|
||||
|
||||

|
||||
# 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.8 to 1.7.9](#update-from-178-to-179)
|
||||
- [Update from 1.7.x to 1.7.8](#update-from-17x-to-178)
|
||||
- [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 VueFileManager Broadcast Server](#install-vuefilemanager-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.1
|
||||
- MySQL 5.6+
|
||||
- Nginx or Apache
|
||||
- Nginx or Apache (Nginx recommended)
|
||||
|
||||
**These PHP Extensions are require:**
|
||||
|
||||
|
||||
**These PHP Extensions are required:**
|
||||
|
||||
- finfo
|
||||
- Intl
|
||||
- GD
|
||||
- BCMath
|
||||
- PDO
|
||||
- SQLite
|
||||
- SQLite3
|
||||
- Ctype
|
||||
- Fileinfo
|
||||
- JSON
|
||||
@@ -70,67 +59,57 @@ 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.
|
||||
|
||||
#### 7. Set up Cron
|
||||
### 7. Set up Cron
|
||||
|
||||
Add the following Cron entry to your server
|
||||
```
|
||||
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
|
||||
```
|
||||
#### If you are running VueFileManager on shared web hosting (CPanel, Plesk etc.)
|
||||
1. Create new cron job
|
||||
2. Set execution cycle for every minute
|
||||
3. Login to the VueFileManager as admin and go to the admin dashboard, you will see command which you have to copy and paste into the command input.
|
||||
|
||||
## 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.
|
||||
#### If you are running VueFileManager on linux server
|
||||
1. Go to the terminal and run command `crontab -e`
|
||||
2. Login to the VueFileManager as admin and go to the admin dashboard, you will see command which you have to copy and paste into the end of file.
|
||||
3. Leave crontab and save the file.
|
||||
|
||||
```
|
||||
memory_limit = 512M
|
||||
upload_max_filesize = 128M
|
||||
post_max_size = 128M
|
||||
max_file_uploads = 50
|
||||
max_execution_time = 3600
|
||||
```
|
||||
|
||||
## 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.
|
||||
|
||||
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;
|
||||
@@ -190,102 +169,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.8 to 1.7.9
|
||||
After uploaded new files, log in as admin to the app and go to `your-domain.com/service/upgrade-database`. This will upgrade your database on the background.
|
||||
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
|
||||
|
||||
After that, **update path to your project in command below** and add the following **Cron** entry to your server:
|
||||
## Install VueFileManager 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.
|
||||
|
||||
### 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:
|
||||
```
|
||||
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
|
||||
cd /var/www/sockets
|
||||
```
|
||||
|
||||
That's all.
|
||||
|
||||
## Update from 1.7.x to 1.7.8
|
||||
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.
|
||||
|
||||
## Update from 1.6.x to 1.7
|
||||
|
||||
For those, who purchase extended licence, place these lines at the end of your `/.env` file:
|
||||
Run installation command for websocket server. You will be prompted to type host of which you want to allow incoming requests.
|
||||
```
|
||||
CASHIER_LOGGER=stack
|
||||
CASHIER_CURRENCY=
|
||||
STRIPE_KEY=
|
||||
STRIPE_SECRET=
|
||||
STRIPE_WEBHOOK_SECRET=
|
||||
CASHIER_PAYMENT_NOTIFICATION=App\Notifications\ConfirmPayment
|
||||
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.
|
||||
|
||||
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:
|
||||
Then, create nginx config for your subdomain:
|
||||
```
|
||||
GET /api/public/pricing
|
||||
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;
|
||||
|
||||
## 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).
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:6001;
|
||||
proxy_read_timeout 60;
|
||||
proxy_connect_timeout 60;
|
||||
proxy_redirect off;
|
||||
|
||||
## 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.
|
||||
# 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 log in to your stripe dashboard, and you will find taxes under `Dashboard / Products / Tax Rates`.
|
||||
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
|
||||
```
|
||||
@@ -295,87 +380,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
|
||||
|
||||
|
||||
17433
_ide_helper.php
17433
_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,69 +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 App\Share;
|
||||
use Carbon\Carbon;
|
||||
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->call(function () {
|
||||
$this->delete_expired_shared_links();
|
||||
})->hourly();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the commands for the application.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function commands()
|
||||
{
|
||||
$this->load(__DIR__ . '/Commands');
|
||||
|
||||
require base_path('routes/console.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get and delete expired shared links
|
||||
*/
|
||||
protected function delete_expired_shared_links(): void
|
||||
{
|
||||
// Get all shares with expiration time
|
||||
$shares = Share::whereNotNull('expire_in')->get();
|
||||
|
||||
$shares->each(function ($share) {
|
||||
|
||||
// Get dates
|
||||
$created_at = Carbon::parse($share->created_at);
|
||||
|
||||
// If time was over, then delete share record
|
||||
if ($created_at->diffInHours(Carbon::now()) >= $share->expire_in) {
|
||||
$share->delete();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -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', json_decode($settings->pluck('value', 'name')->toJson()))
|
||||
->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,expire_in'])
|
||||
->where('user_id', $user_id)
|
||||
->whereIn('unique_id', $folder_ids)
|
||||
->get();
|
||||
|
||||
$files = FileManagerFile::with(['parent', 'shared:token,id,item_id,permission,protected,expire_in'])
|
||||
->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,expire_in'])
|
||||
->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,expire_in'])
|
||||
->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,expire_in'])
|
||||
->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,109 +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,
|
||||
'expire_in' => $request->expiration,
|
||||
'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,
|
||||
'expire_in' => $request->expiration,
|
||||
'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,175 +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;
|
||||
use Schema;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start maintenance mode
|
||||
*/
|
||||
public function up() {
|
||||
$command = Artisan::call('up');
|
||||
|
||||
if ($command === 0) {
|
||||
echo 'System is in production mode';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* End maintenance mode
|
||||
*/
|
||||
public function down() {
|
||||
$command = Artisan::call('down');
|
||||
|
||||
if ($command === 0) {
|
||||
echo 'System is in maintenance mode';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Upgrade database
|
||||
*/
|
||||
public function upgrade_database()
|
||||
{
|
||||
/*
|
||||
* Upgrade expire_in in shares table
|
||||
*
|
||||
* @since v1.7.9
|
||||
*/
|
||||
if (! Schema::hasColumn('shares', 'expire_in')) {
|
||||
|
||||
$command = Artisan::call('migrate', [
|
||||
'--force' => true
|
||||
]);
|
||||
|
||||
if ($command === 0) {
|
||||
echo 'Operation was successful.';
|
||||
}
|
||||
|
||||
if ($command === 1) {
|
||||
echo 'Operation failed.';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,410 +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 = Share::where(\DB::raw('BINARY `token`'), $token)
|
||||
->first();
|
||||
|
||||
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,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
|
||||
class InvoiceCollection extends ResourceCollection
|
||||
{
|
||||
public $collects = InvoiceResource::class;
|
||||
|
||||
/**
|
||||
* Transform the resource collection into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => $this->collection,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -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,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,expire_in'])
|
||||
->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,expire_in');
|
||||
}
|
||||
|
||||
/**
|
||||
* 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'];
|
||||
}
|
||||
895
changelog.md
Normal file
895
changelog.md
Normal file
@@ -0,0 +1,895 @@
|
||||
## Version 2.2.7
|
||||
#### Release date: 20. August 2022
|
||||
- fixed upload button issue in mobile
|
||||
|
||||
## Version 2.2.6
|
||||
#### Release date: 17. August 2022
|
||||
- fixed upload button issue
|
||||
|
||||
## Version 2.2.5
|
||||
#### Release date: 11. August 2022
|
||||
- improved tracking for Google Analytics
|
||||
|
||||
## Version 2.2.4
|
||||
#### Release date: 8. August 2022
|
||||
- Account verification email is now sending in preferred app language
|
||||
- Fixed issue where metered billing mode still count in some cases members after team folder was deleted
|
||||
- In case if cron isn't set, in Settings/Server tab you will see suggestions for cron command
|
||||
|
||||
## Version 2.2.3
|
||||
#### Release date: 6. August 2022
|
||||
- Subscription module is now available for Regular license type
|
||||
|
||||
## Version 2.2.2
|
||||
#### Release date: 16. July 2022
|
||||
- Fixed issue when email wasn't sent in active app language
|
||||
- Fixed issue with subscription module loading
|
||||
|
||||
## Version 2.2.1
|
||||
#### Release date: 1. July 2022
|
||||
### New Usage Restriction Rules for User Accounts for Metered Billing
|
||||
- Allow limiting max usage before users will be forced to increase balance in first month of account existence
|
||||
- Force users to increase balance when usage is bigger than their current balance
|
||||
|
||||
#### Release date: 29. Jun 2022
|
||||
- Fixed reCaptcha for the contact form
|
||||
|
||||
## Version 2.2.0.13
|
||||
#### Release date: 29. Jun 2022
|
||||
- Extended login time up to 3 months
|
||||
- Fixed deleted at language string in grid view browsed in trash section
|
||||
|
||||
- ## Version 2.2.0.12
|
||||
#### Release date: 28. Jun 2022
|
||||
- Fixed paystack transaction issue
|
||||
|
||||
## Version 2.2.0.11
|
||||
#### Release date: 27. Jun 2022
|
||||
- Added hint to set cron command in dashboard panel when cron is not set correctly
|
||||
|
||||
## Version 2.2.0.10
|
||||
#### Release date: 27. Jun 2022
|
||||
- Fixed issue with downloading certain file types when you are using Backblaze storage driver
|
||||
- Fixed issue when Google Analytics doesn't record visitors
|
||||
|
||||
## Version 2.2.0.9
|
||||
#### Release date: 23. Jun 2022
|
||||
- Added spinner when pdf is loading
|
||||
- Set sandbox/live mode in PayPal key configuration setup form
|
||||
- Fixed issue when after deleting user, the related subscription wasn't deleted
|
||||
- Fixed issue when you perform composer update with private repository
|
||||
- Fixed issue where change in sorting option will duplicate the content in file view
|
||||
- Fixed issue where Dragged & Dropped folder from desktop didn't start uploading
|
||||
- Fixed issue when you upload empty .txt file, it stops the upload process
|
||||
|
||||
## Version 2.2.0.8
|
||||
#### Release date: 15. Jun 2022
|
||||
- Fixed issue when you tried switch to another language, the language stay same
|
||||
|
||||
## Version 2.2.0.7
|
||||
#### Release date: 13. Jun 2022
|
||||
- Solved issue when you click on the PayPal logo it makes the new copy of the payment buttons
|
||||
|
||||
## Version 2.2.0.6
|
||||
#### Release date: 13. Jun 2022
|
||||
- Solved issue when user wasn't redirected into stripe checkout
|
||||
|
||||
## Version 2.2.0.5
|
||||
#### Release date: 12. Jun 2022
|
||||
- Solved issue with showing trash content (Affected since 2.2.0)
|
||||
|
||||
## 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/saas-billing": "^1.0",
|
||||
"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": "github",
|
||||
"url": "https://github.com/makingcg/saas-billing.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"
|
||||
}
|
||||
}
|
||||
|
||||
13945
composer.lock
generated
13945
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'),
|
||||
|
||||
];
|
||||
@@ -24,23 +24,23 @@ return [
|
||||
'content' => [
|
||||
[
|
||||
'name' => 'section_features',
|
||||
'value' => '1',
|
||||
'value' => 1,
|
||||
],
|
||||
[
|
||||
'name' => 'section_feature_boxes',
|
||||
'value' => '1',
|
||||
'value' => 1,
|
||||
],
|
||||
[
|
||||
'name' => 'section_pricing_content',
|
||||
'value' => '1',
|
||||
'value' => 1,
|
||||
],
|
||||
[
|
||||
'name' => 'section_get_started',
|
||||
'value' => '1',
|
||||
'value' => 1,
|
||||
],
|
||||
[
|
||||
'name' => 'header_title',
|
||||
'value' => 'Simple <span style="color: #41B883">&</span> Powerful Personal Cloud Storage',
|
||||
'value' => 'Simple <span class="text-theme">&</span> Powerful Personal Cloud Storage',
|
||||
],
|
||||
[
|
||||
'name' => 'header_description',
|
||||
@@ -48,7 +48,7 @@ return [
|
||||
],
|
||||
[
|
||||
'name' => 'features_title',
|
||||
'value' => 'The Fastest Growing <span style="color: #41B883">File Manager</span> on the CodeCanyon Market',
|
||||
'value' => 'The Fastest Growing <span class="text-theme">File Manager</span> on the CodeCanyon Market',
|
||||
],
|
||||
[
|
||||
'name' => 'features_description',
|
||||
@@ -80,7 +80,7 @@ return [
|
||||
],
|
||||
[
|
||||
'name' => 'pricing_title',
|
||||
'value' => 'Pick the <span style="color: #41B883;">Best Plan</span> For Your Needs',
|
||||
'value' => 'Pick the <span class="text-theme">Best Plan</span> For Your Needs',
|
||||
],
|
||||
[
|
||||
'name' => 'pricing_description',
|
||||
@@ -88,7 +88,7 @@ return [
|
||||
],
|
||||
[
|
||||
'name' => 'get_started_title',
|
||||
'value' => 'Ready to Get <span style="color: #41B883">Started</span><br> With Us?',
|
||||
'value' => 'Ready to Get <span class="text-theme">Started</span><br> With Us?',
|
||||
],
|
||||
[
|
||||
'name' => 'get_started_description',
|
||||
@@ -96,7 +96,35 @@ return [
|
||||
],
|
||||
[
|
||||
'name' => 'footer_content',
|
||||
'value' => '© 2020 Simple & Powerful Personal Cloud Storage. Developed by <a href="https://hi5ve.digital" target="_blank">Hi5Ve.Digital</a>',
|
||||
'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,
|
||||
],
|
||||
[
|
||||
'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,
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user