mirror of
https://github.com/donaldzou/WGDashboard.git
synced 2025-07-16 18:16:59 +00:00
Compare commits
1268 Commits
v2.0.1-bet
...
main
Author | SHA1 | Date | |
---|---|---|---|
|
8abadd1070 | ||
|
1483ef83d9 | ||
|
dbed799e20 | ||
|
4602b68425 | ||
|
2d3eaedaa7 | ||
|
4d60b21a5f | ||
|
50ee8374ee | ||
|
65eb23e8ce | ||
|
5c76b18ddd | ||
|
fc6f5d2535 | ||
|
6a0348e9dc | ||
|
90e6409b1e | ||
|
96b28a8e9b | ||
|
a818e87e96 | ||
|
dc715758a6 | ||
|
87069329d8 | ||
|
8a380a4545 | ||
|
a5e18cb761 | ||
|
e9da3e7b6a | ||
|
289fa23728 | ||
|
c117ee61d5 | ||
|
7385932e52 | ||
|
cb90b69b3f | ||
|
8d0e31872a | ||
|
881925fd43 | ||
|
3a2f744f0a | ||
|
9dc9e668c5 | ||
|
39477c8de8 | ||
|
1b0bb95e81 | ||
|
cd5a4bec52 | ||
|
43070ab809 | ||
|
532fedbb62 | ||
|
585bf37783 | ||
|
cad364e407 | ||
|
45457c5b38 | ||
|
4e9142b5be | ||
|
207b365d40 | ||
|
1ec95a0d86 | ||
|
db4b9ccc7a | ||
|
a86d0c74d3 | ||
|
354f4e47df | ||
|
84167650b8 | ||
|
15c12a81f1 | ||
|
249ae584c3 | ||
|
b04f7b2d2c | ||
|
630ce459cb | ||
|
a7a30fb282 | ||
|
ab5abe9bcf | ||
|
7834fff541 | ||
|
ef8849e8a9 | ||
|
78bedf9ad6 | ||
|
6ec757ab66 | ||
|
7d71299c51 | ||
|
bea37aee7f | ||
|
5323687ea5 | ||
|
d1372a4c43 | ||
|
c9249a164a | ||
|
6f105f2626 | ||
|
e4c08896f4 | ||
|
e85a0df9b7 | ||
|
a5b7eabd97 | ||
|
f3688431a3 | ||
|
44e714352d | ||
|
60da68c994 | ||
|
11288fac20 | ||
|
fe9d373444 | ||
|
cce31f9b0b | ||
|
ca779ed5ad | ||
|
eb0eaaae2e | ||
|
9631b97694 | ||
|
6f036876c8 | ||
|
bd47179ea4 | ||
|
418c6bd88b | ||
|
ada4c4f816 | ||
|
91b499fb14 | ||
|
1f73adffd6 | ||
|
82bd313e7a | ||
|
14cbfe47b9 | ||
|
f2d4ff6dc4 | ||
|
bf33a70727 | ||
|
e1bdcbd581 | ||
|
051c1e7622 | ||
|
3b176474ff | ||
|
15f1b33ea6 | ||
|
0603d4076a | ||
|
ac94f10dc3 | ||
|
bbb92490e9 | ||
|
2cb63092c0 | ||
|
b9bcb59592 | ||
|
e083adc022 | ||
|
c3cd38fe9f | ||
|
a7c2db5e99 | ||
|
4926ee5117 | ||
|
e7723ac3db | ||
|
8dbfb93e4e | ||
|
6096366756 | ||
|
8e4cf12512 | ||
|
b61fa1f870 | ||
|
ac3cf9e4b1 | ||
|
e18463f059 | ||
|
ee54e08d18 | ||
|
3c07df6496 | ||
|
2117b828c8 | ||
|
28d9694432 | ||
|
7d977700e6 | ||
|
33942945d0 | ||
|
8d7d78db46 | ||
|
3268cc30ea | ||
|
8830ebe34f | ||
|
1d9adba6dd | ||
|
71be73777e | ||
|
7709f70ef1 | ||
|
9b528b84e1 | ||
|
c53a4d4861 | ||
|
766173df3d | ||
|
7f65cae891 | ||
|
bc56ecb85c | ||
|
50c3151301 | ||
|
d49ec0a81e | ||
|
6692028762 | ||
|
b71c357958 | ||
|
03b7621f3e | ||
|
2bcf24bd84 | ||
|
cc5aa05b12 | ||
|
3232c5c4ce | ||
|
72a52f5cd6 | ||
|
bda48a56e0 | ||
|
09cdcf8e53 | ||
|
a4d5b41ca7 | ||
|
9fa0d91d06 | ||
|
510f60bdeb | ||
|
30fe827253 | ||
|
8f0f4b168b | ||
|
cd11c4beb6 | ||
|
4d49cc413a | ||
|
3d50a58a31 | ||
|
d5701230fa | ||
|
ab945d6afe | ||
|
b4f8a36d43 | ||
|
608c1b4eb6 | ||
|
edf3c42157 | ||
|
c523cec113 | ||
|
6f8b987d42 | ||
|
d0d0642bdf | ||
|
924d760e3b | ||
|
f8c207ca2b | ||
|
ada1edd0b7 | ||
|
c79333db61 | ||
|
13778bed87 | ||
|
83b4d96f42 | ||
|
6cf96de0b4 | ||
|
481fadc7fc | ||
|
44f2c59e56 | ||
|
83589a912f | ||
|
fab9f03e7d | ||
|
928c83b13c | ||
|
72f20bc69b | ||
|
8293d5379d | ||
|
1d29445a8b | ||
|
5c308d757f | ||
|
5bf16004c9 | ||
|
417fa437b7 | ||
|
43f893c921 | ||
|
8ad9af4bc2 | ||
|
b3931bdc9d | ||
|
7ac153848b | ||
|
7689ebcac5 | ||
|
bf7adf9ca9 | ||
|
51ab8c556a | ||
|
149a8e910d | ||
|
310746b8cd | ||
|
6681303450 | ||
|
3228f37f09 | ||
|
421785bf6a | ||
|
308e8ca8c7 | ||
|
cb068ef70e | ||
|
acd3ec782f | ||
|
12d1e5b8d0 | ||
|
b165cdbd79 | ||
|
66f4507dee | ||
|
a724e1cb58 | ||
|
f942809de0 | ||
|
8043f77e02 | ||
|
1db9ba90d8 | ||
|
464fa59cb6 | ||
|
a8e2cbf55b | ||
|
fecd8dab38 | ||
|
13a833e3ed | ||
|
8d4784052a | ||
|
d9e9b41861 | ||
|
f0c3ef0aa1 | ||
|
3888831679 | ||
|
1a32fad324 | ||
|
d842ae9540 | ||
|
d0177b7504 | ||
|
e3842b25f3 | ||
|
a29b59c9cd | ||
|
f94eb97aa4 | ||
|
86017b79eb | ||
|
bc22fa5fad | ||
|
d6b70028ff | ||
|
0f7f9acd58 | ||
|
20633a6d1a | ||
|
a23856270d | ||
|
55543e370e | ||
|
8137a46c68 | ||
|
aeb9597c71 | ||
|
5067485e94 | ||
|
dfd456c7dc | ||
|
0ccb07e683 | ||
|
ca67a6897f | ||
|
0390227641 | ||
|
395b0982db | ||
|
f096ab4da7 | ||
|
d5ec9f7640 | ||
|
5732867407 | ||
|
31842f4c12 | ||
|
d5168d2da6 | ||
|
cac5ec836b | ||
|
ee9569e7d4 | ||
|
95df7de026 | ||
|
d3a5bd374d | ||
|
43ac3dddf1 | ||
|
1174328de3 | ||
|
dda54fb907 | ||
|
92ea808a5d | ||
|
2bc3a75c94 | ||
|
07ef97ce7c | ||
|
5fe3539331 | ||
|
4bc3bd5f13 | ||
|
4abce854d7 | ||
|
3b5c73992e | ||
|
c5abea2944 | ||
|
8e5cf14ebc | ||
|
7c8410ab86 | ||
|
369b4b92cc | ||
|
c50bb70383 | ||
|
d84b2060f0 | ||
|
afcf6024e6 | ||
|
3542bd6668 | ||
|
69b9116dd5 | ||
|
a2db4f06b1 | ||
|
b60b0fb511 | ||
|
0c1e9a6bb5 | ||
|
2692f92cb9 | ||
|
a43c8b4b00 | ||
|
6f15389411 | ||
|
f055241802 | ||
|
ac77c3a390 | ||
|
5cd99f2edc | ||
|
7c70fbec30 | ||
|
ac0dc3196f | ||
|
7f4da826b1 | ||
|
cc2af4371f | ||
|
2a79a03d38 | ||
|
47aac7fe33 | ||
|
d4055884b1 | ||
|
61658e847a | ||
|
bd714223ce | ||
|
060154cb89 | ||
|
99a1bfca9d | ||
|
4379f30628 | ||
|
b501244577 | ||
|
6f7b9815ca | ||
|
227bd088f7 | ||
|
b1d6ecb07c | ||
|
41772f28bd | ||
|
393dac1c99 | ||
|
db9d0be6c7 | ||
|
f0774ec273 | ||
|
d4a4d28b58 | ||
|
3ec97021bd | ||
|
56cf972373 | ||
|
2f3ae4c1af | ||
|
bc3dd04e12 | ||
|
4e8fc1b431 | ||
|
cd39aa2968 | ||
|
87ea3fc982 | ||
|
f74a511778 | ||
|
202461fe48 | ||
|
2af6687351 | ||
|
e603af5f24 | ||
|
84069ee882 | ||
|
edbb5cef92 | ||
|
a62c54b4ed | ||
|
41df7c04c3 | ||
|
9b783a8322 | ||
|
57db4df618 | ||
|
9d1081bd56 | ||
|
cc3773817b | ||
|
8956355e57 | ||
|
645db97c14 | ||
|
07a04dc507 | ||
|
a7317af413 | ||
|
ba6d6b8851 | ||
|
3726810108 | ||
|
4f92a7edf3 | ||
|
5d84b61f18 | ||
|
cd1329ec67 | ||
|
48a58b2b69 | ||
|
9b64aba8bf | ||
|
cae8264d98 | ||
|
95d8985336 | ||
|
b26ae90807 | ||
|
66d171c432 | ||
|
40463d9831 | ||
|
eb7dee013d | ||
|
1a878599b1 | ||
|
b9e25abdd9 | ||
|
c612022717 | ||
|
31e7f02b8d | ||
|
75747a2979 | ||
|
a85a8668a7 | ||
|
cca5fd859c | ||
|
2ed49abb1b | ||
|
409e6d49b2 | ||
|
93cfc482b8 | ||
|
85be6d53d0 | ||
|
bf6f58eb5e | ||
|
cd9d17ab18 | ||
|
e0bc6a10d0 | ||
|
ccfc1ad166 | ||
|
812060240f | ||
|
715a266ca4 | ||
|
fa4b3ece56 | ||
|
aac2a002bb | ||
|
8574acaf6e | ||
|
ddf4639354 | ||
|
9bd394f351 | ||
|
6899d48aae | ||
|
514e1ca8d0 | ||
|
eba5be010a | ||
|
f578d5c1c9 | ||
|
e58b1d670b | ||
|
c2642259b4 | ||
|
c47b0c9741 | ||
|
f425156cad | ||
|
7d7e31120e | ||
|
ccd247d154 | ||
|
53df6849f7 | ||
|
c2080bd1b3 | ||
|
9e93f8c2a5 | ||
|
907a142c8d | ||
|
d7bc8cd8e4 | ||
|
bb3e00a695 | ||
|
af5e7974c3 | ||
|
6a88959ec4 | ||
|
7b59149f90 | ||
|
3e01079caf | ||
|
d92e62e40b | ||
|
b4952dea7b | ||
|
00acb04329 | ||
|
939dd0591e | ||
|
febdb2a9e0 | ||
|
bcfd9fc1c9 | ||
|
e4964da5d4 | ||
|
a042298a4a | ||
|
908be168a9 | ||
|
d780bb3937 | ||
|
461e7e8913 | ||
|
819e8b73c3 | ||
|
627b7087a1 | ||
|
f23cf555e1 | ||
|
000978e4fb | ||
|
74782483bd | ||
|
c5f9387b92 | ||
|
57583b6747 | ||
|
434c236210 | ||
|
807bb97b6a | ||
|
da53bd44d1 | ||
|
3b01943649 | ||
|
3340f9c6ee | ||
|
b21cfe8504 | ||
|
97ab6ec299 | ||
|
7fda58e5c8 | ||
|
db6e820d1d | ||
|
8c2e1875ca | ||
|
bd95fe9af1 | ||
|
a517f89234 | ||
|
f994e7bfa8 | ||
|
28716924c9 | ||
|
b597f90f5b | ||
|
5912420467 | ||
|
90f35fd680 | ||
|
3e2d6e71b9 | ||
|
cbffdd829a | ||
|
d77e092948 | ||
|
1f5e10e784 | ||
|
68e3813c6c | ||
|
c9d78e3f67 | ||
|
b4f3fb3b30 | ||
|
bf7fb898f9 | ||
|
6c5e0543b4 | ||
|
578a1db62f | ||
|
4524a55b23 | ||
|
f942eaf1b6 | ||
|
6a4d16fae9 | ||
|
53b234252f | ||
|
9287e81ef1 | ||
|
5462326f79 | ||
|
b8b3992159 | ||
|
8214000713 | ||
|
94337a33d4 | ||
|
8ddee03338 | ||
|
8e2934533b | ||
|
71ee784003 | ||
|
597528e9b7 | ||
|
45fbbf9218 | ||
|
c7a4a01fee | ||
|
fa04ad1395 | ||
|
abdd85bdd5 | ||
|
dba55d57e8 | ||
|
9819c96717 | ||
|
1b0885bffe | ||
|
c0a8540ab8 | ||
|
f3b95f03a1 | ||
|
5f06f3da52 | ||
|
10a7fb809b | ||
|
d3ea1f3da2 | ||
|
74d0471a6f | ||
|
a1c1805409 | ||
|
b843145bed | ||
|
119920b665 | ||
|
6190e2d290 | ||
|
79de99d146 | ||
|
56a9b3df0a | ||
|
4df6413dba | ||
|
fcd0ada639 | ||
|
6b6bd155aa | ||
|
9c91b1bca5 | ||
|
1a5c0e5b24 | ||
|
981b30e4af | ||
|
30c84d8cbf | ||
|
4c538c54a8 | ||
|
ad7a8f1d08 | ||
|
f02a07dab4 | ||
|
c61b0fc1e1 | ||
|
fed7dfcb73 | ||
|
0d69c811ab | ||
|
83274add22 | ||
|
7497d1b6d4 | ||
|
239bc144e3 | ||
|
1ece64abe1 | ||
|
915783699b | ||
|
43f6bd41c9 | ||
|
98c017dd56 | ||
|
811ed3251b | ||
|
665b0f1484 | ||
|
9e26d845da | ||
|
6ddf20f5ce | ||
|
27ed0710cc | ||
|
cb87c9f345 | ||
|
e1e147c8f0 | ||
|
b37d889de9 | ||
|
b61c9bfc5e | ||
|
e963788a81 | ||
|
3ef4798e09 | ||
|
21730102ae | ||
|
b1ae05152e | ||
|
cc87f01e2f | ||
|
85dfa1b078 | ||
|
fdff54e11e | ||
|
0894f38660 | ||
|
f643d8ef25 | ||
|
e437284980 | ||
|
f6e0d330ac | ||
|
890cbf0f36 | ||
|
36cf2ea2e8 | ||
|
a8f7bd0280 | ||
|
aa6517046d | ||
|
42e4d8c7ba | ||
|
3d1da38cbc | ||
|
5ae8490999 | ||
|
715675b2f1 | ||
|
0d7198a26c | ||
|
d8b7ce6d9b | ||
|
d032ca31e3 | ||
|
67b49c0585 | ||
|
c23242f18e | ||
|
c23f7a3ee2 | ||
|
7e3e957649 | ||
|
b8f304dfd3 | ||
|
e895ac9245 | ||
|
77579a71e8 | ||
|
cc7e13cdbf | ||
|
5df3886e42 | ||
|
cc179a05d0 | ||
|
ec5f4f2778 | ||
|
084c95f0e5 | ||
|
3b78cfe0fd | ||
|
160ce3338d | ||
|
d425cfe1aa | ||
|
6ff286f9b4 | ||
|
b930461434 | ||
|
ee6bb24506 | ||
|
b69124c89f | ||
|
f089e4a1ce | ||
|
7dedb5c076 | ||
|
3276c9a84c | ||
|
04ef2ea3b6 | ||
|
04a2f27a75 | ||
|
d962f59884 | ||
|
fd3bd4567a | ||
|
29e7a5ecdb | ||
|
4956b0d89d | ||
|
3bc54a4e16 | ||
|
29ecd602ec | ||
|
1425dec564 | ||
|
2bb1c0c999 | ||
|
97f3daae70 | ||
|
c53a7ef6fe | ||
|
b97fc16ad9 | ||
|
eaac12ddc8 | ||
|
183be5da0e | ||
|
ace0953c87 | ||
|
1fd7e7833d | ||
|
aa5801d73b | ||
|
d1ea8081e4 | ||
|
49467c906d | ||
|
79bd575aca | ||
|
e533a0e405 | ||
|
94b597d29a | ||
|
504fefff94 | ||
|
ff794a3638 | ||
|
efb9a34cb8 | ||
|
a93291b38f | ||
|
dfc9eab9d3 | ||
|
3c74b0b1ef | ||
|
9b981fcea8 | ||
|
9d3a189d77 | ||
|
01c0175e8f | ||
|
d7e5e2f381 | ||
|
c27de8b9a5 | ||
|
c3a55f8b69 | ||
|
78b65a799e | ||
|
6a30cee611 | ||
|
bc19e3a6ff | ||
|
5a8f2fa2be | ||
|
81168c27c6 | ||
|
a606626053 | ||
|
adeb57864b | ||
|
747f1a6fae | ||
|
3ac9c23573 | ||
|
5ad9c0e77a | ||
|
ba5ba2f1d6 | ||
|
4902b5f351 | ||
|
166fcda193 | ||
|
83560bc775 | ||
|
4ffb00c9f5 | ||
|
fbac41a774 | ||
|
c837ab8693 | ||
|
1cc321ddff | ||
|
7861cffb91 | ||
|
82a472f368 | ||
|
cfe59774e7 | ||
|
1098475473 | ||
|
4546e795ef | ||
|
bb0aba586b | ||
|
204b995e6c | ||
|
321b7b4cee | ||
|
413377fbb9 | ||
|
e2e821881c | ||
|
51712ed2a8 | ||
|
27de7ddbf8 | ||
|
bb700f3a3d | ||
|
563268558b | ||
|
56744cec7b | ||
|
87696a2e6c | ||
|
79f1c20f8a | ||
|
4e5638df36 | ||
|
71349f35e4 | ||
|
2cb06bb4bb | ||
|
5e1769b81f | ||
|
e344f28265 | ||
|
2297d6b85b | ||
|
baaecdbd8c | ||
|
31d8af642d | ||
|
27c67ec202 | ||
|
4833a29e57 | ||
|
4a2f3e0372 | ||
|
f3eeff4ec8 | ||
|
221e03ecfa | ||
|
392a9c6f53 | ||
|
145d12b2c8 | ||
|
0c5033ff79 | ||
|
5f46f54dfd | ||
|
d4819b13eb | ||
|
9dd9be3b8c | ||
|
dd38809866 | ||
|
c414725f12 | ||
|
d3c8a350a4 | ||
|
e04b748b91 | ||
|
1eee8c4725 | ||
|
2b7a4b170c | ||
|
7c0bf4f137 | ||
|
54bae43d2e | ||
|
25be1155a6 | ||
|
4905d61a1a | ||
|
ff0147bebb | ||
|
7fe4889b6e | ||
|
3c9b1b1833 | ||
|
2a46c873b8 | ||
|
6ed09324ad | ||
|
d1f9c10790 | ||
|
5d041b2fd3 | ||
|
5cea0fa87b | ||
|
6f140eef29 | ||
|
e5850adfd7 | ||
|
6921833ce2 | ||
|
57b9accd97 | ||
|
de94f5b233 | ||
|
b5519a73fb | ||
|
c5d8c2c355 | ||
|
c5b02a426c | ||
|
4cae910b68 | ||
|
b664fccce2 | ||
|
21672f99d1 | ||
|
c269e46892 | ||
|
8534e8cf5b | ||
|
94bf1c2484 | ||
|
b3b30470fc | ||
|
41d91e75fc | ||
|
a97a91b844 | ||
|
f1c577ab76 | ||
|
17a9fe5024 | ||
|
d74a76dee3 | ||
|
c01201b88e | ||
|
833bdf878a | ||
|
891990b2f1 | ||
|
e9ab7029c9 | ||
|
6f681dba09 | ||
|
b3edff947d | ||
|
ce6d80d601 | ||
|
a80a2866de | ||
|
02c2221970 | ||
|
d35bd6e75b | ||
|
f3a2f98864 | ||
|
a3a312e3db | ||
|
f5cb5c4516 | ||
|
d458a28337 | ||
|
a102a780f8 | ||
|
4dbbc32108 | ||
|
b6aedb43ee | ||
|
ec50dcbbd9 | ||
|
bcc983f11f | ||
|
809651054e | ||
|
2e965ceb9e | ||
|
e35f942964 | ||
|
40e6fce281 | ||
|
2139865876 | ||
|
c3cda05d98 | ||
|
548f3db33d | ||
|
a76e9ed98b | ||
|
c0ef41a9bb | ||
|
f6e5d9675a | ||
|
ef028659d8 | ||
|
40f39e918d | ||
|
2ec3ee2734 | ||
|
bc29b89a16 | ||
|
e21853286e | ||
|
c012b8c4a5 | ||
|
48f6c28556 | ||
|
0c1502f801 | ||
|
fec20ed381 | ||
|
252c147dcf | ||
|
453d474104 | ||
|
84cf4a9b66 | ||
|
fb016bebde | ||
|
8f6a738481 | ||
|
b07f958577 | ||
|
8da0fde52a | ||
|
39be16cb63 | ||
|
59d0c0def4 | ||
|
79c03db9a0 | ||
|
0c77823020 | ||
|
deed7e0022 | ||
|
99db8c7335 | ||
|
9fe2aa9ed5 | ||
|
4c80dc256b | ||
|
cafe9e9c11 | ||
|
27ff4e63b6 | ||
|
8020714e07 | ||
|
dbd825ba4b | ||
|
fee6cf29eb | ||
|
56287d8e7a | ||
|
45504eaf95 | ||
|
b8a9b1150a | ||
|
8bd0e43f58 | ||
|
2c83e9e83c | ||
|
53c9ca10a7 | ||
|
75fbdac42e | ||
|
09d54546ca | ||
|
b62fece3d0 | ||
|
284a2b7f64 | ||
|
9c873ccbbd | ||
|
5f72f90031 | ||
|
93cf3c69b8 | ||
|
88f856cbc7 | ||
|
2d5796d161 | ||
|
1d20dc9fcb | ||
|
49502235b5 | ||
|
6e9d71fcf8 | ||
|
27c7e33773 | ||
|
3012619049 | ||
|
d6801966c4 | ||
|
518e29118c | ||
|
acf4f3fbf0 | ||
|
8378030c70 | ||
|
dc7140d486 | ||
|
e3771a1c53 | ||
|
2e9ac00a42 | ||
|
4b8b3acd39 | ||
|
8703798ca0 | ||
|
47ac438844 | ||
|
bd3aa28523 | ||
|
68d0ae4002 | ||
|
6991039640 | ||
|
00611ef9dc | ||
|
3c50e4768a | ||
|
63dc9834be | ||
|
f042e42633 | ||
|
39b80a2e7e | ||
|
fb6e948358 | ||
|
181b0845bf | ||
|
b2a82dcfe5 | ||
|
ed1c05dec9 | ||
|
cd73aef0c9 | ||
|
ed522ec024 | ||
|
16998d1e16 | ||
|
11421d2d32 | ||
|
1af708aaea | ||
|
fbb82fa759 | ||
|
a9f977c3b4 | ||
|
5669e22548 | ||
|
da4bb9b83d | ||
|
c2cbaf0937 | ||
|
d81dce536c | ||
|
8e1e2c5b85 | ||
|
959d5e6822 | ||
|
036a0b4cb3 | ||
|
c038f14374 | ||
|
343cf91643 | ||
|
4fe70a4c46 | ||
|
59f7200512 | ||
|
0335e709c2 | ||
|
a7bb5ac21b | ||
|
99655cab33 | ||
|
348e574154 | ||
|
f35dee8643 | ||
|
168412c2e7 | ||
|
b9832542fb | ||
|
316545b253 | ||
|
348a57a0d8 | ||
|
a3f5654816 | ||
|
8207afe806 | ||
|
e15b8f8092 | ||
|
e6c99028d6 | ||
|
2e691d7c26 | ||
|
6c87812780 | ||
|
798a3632cf | ||
|
aa1d0aabd2 | ||
|
f348e691fa | ||
|
0dfda83e45 | ||
|
56044fa3f7 | ||
|
4c69fd4f60 | ||
|
92e3f7a6a3 | ||
|
76d0618d6e | ||
|
80c3a99eb1 | ||
|
91e3a3237b | ||
|
8c8c5a5826 | ||
|
b9370955d6 | ||
|
2761e728f7 | ||
|
f418bf4f63 | ||
|
3d046e4369 | ||
|
b6eb6f2d70 | ||
|
45ce3e26c1 | ||
|
ae91cedf76 | ||
|
b2a6b484b5 | ||
|
95c4fa56cc | ||
|
e8c56afa8e | ||
|
ddc3b1f6c2 | ||
|
d33d886574 | ||
|
0487980d2f | ||
|
e68257d6c9 | ||
|
ea0bbab680 | ||
|
5d4a8136c5 | ||
|
c98d851cd2 | ||
|
42fa89db7a | ||
|
1a70acc6f2 | ||
|
ee0a287112 | ||
|
cf16a66c63 | ||
|
4544b17c94 | ||
|
8119c9da51 | ||
|
baf4d75c01 | ||
|
ac9eff0fcc | ||
|
dc57bd92ff | ||
|
3c56a2c868 | ||
|
2d2ab10a24 | ||
|
ac906c9994 | ||
|
480406d579 | ||
|
47efb644b7 | ||
|
fd0e519e41 | ||
|
0c8bb990d0 | ||
|
bd7139827b | ||
|
4f648aff52 | ||
|
3feb45dc01 | ||
|
0489dc7c33 | ||
|
a30843cff9 | ||
|
3a34a0eb40 | ||
|
e3f82e136a | ||
|
8a7df4ba9f | ||
|
e86d1a4c7a | ||
|
5b9d0b60a1 | ||
|
7eff2f0c49 | ||
|
97236bb01d | ||
|
9c6aa12f48 | ||
|
96ccb03eea | ||
|
55f55820c5 | ||
|
955839d513 | ||
|
a650e628e5 | ||
|
54142b73fb | ||
|
55e0d2695d | ||
|
2f90ab15dc | ||
|
fd3fc66bfc | ||
|
a352a94d8a | ||
|
410b81f46f | ||
|
aa3711c5cc | ||
|
d6b1f97a04 | ||
|
b4e8e57a22 | ||
|
9644e6195c | ||
|
764e0c7607 | ||
|
97d640dd40 | ||
|
d2915b5b05 | ||
|
f274f6fd18 | ||
|
f507ac2569 | ||
|
208cbd6d89 | ||
|
cd2aa2902a | ||
|
fa2d7fa3da | ||
|
7463767781 | ||
|
958bc864c9 | ||
|
4484668750 | ||
|
d5dea4b87f | ||
|
0fdef6a0a2 | ||
|
bd71b6bad8 | ||
|
9b7887b279 | ||
|
3960e43872 | ||
|
201c8f9ec9 | ||
|
8c8374a08c | ||
|
467595afc9 | ||
|
acb54f098c | ||
|
5755d13460 | ||
|
2c3500315d | ||
|
47ea60c0cd | ||
|
18b18c1396 | ||
|
ff227de5fa | ||
|
6799692811 | ||
|
c6173f7f6f | ||
|
d0e4dabc44 | ||
|
f815dae300 | ||
|
b3bd6bb39e | ||
|
71df6409c2 | ||
|
e4f9a1e0cf | ||
|
ca6a05e393 | ||
|
c0d26164dc | ||
|
76fe2a1ba9 | ||
|
8cbdb54402 | ||
|
764ef80a62 | ||
|
0c37d93c01 | ||
|
c57a5128e5 | ||
|
6cf4eba20a | ||
|
6825d728c2 | ||
|
6d3091b2a2 | ||
|
61473877a4 | ||
|
52989c8f5c | ||
|
b64ba2ef16 | ||
|
461ae99dd8 | ||
|
8681df6f02 | ||
|
ba081ee442 | ||
|
cf90d05115 | ||
|
658c6554af | ||
|
94d9d608f7 | ||
|
015b50be5f | ||
|
85970f8c96 | ||
|
1740ab0bbe | ||
|
9d2b5593a2 | ||
|
881d62d69d | ||
|
935129f0a5 | ||
|
1a9bdc5e6d | ||
|
1f565bca10 | ||
|
da089197a3 | ||
|
2df8f41d6c | ||
|
4e4f0d4c97 | ||
|
eaad22c0a1 | ||
|
63e8553a09 | ||
|
b65828416f | ||
|
48dc8033f5 | ||
|
2d838b69fd | ||
|
6c529a6908 | ||
|
9baefec541 | ||
|
327d66bb80 | ||
|
760a4dfcb9 | ||
|
ceb8cdd337 | ||
|
570c754eec | ||
|
8ed75d1d21 | ||
|
54710b8221 | ||
|
ff794033e1 | ||
|
f0f486da9e | ||
|
aedcfd1d24 | ||
|
44e738acf5 | ||
|
701b45c286 | ||
|
72fe687d82 | ||
|
632cd66b57 | ||
|
20530c000e | ||
|
8824786fb4 | ||
|
bdeb4a4efe | ||
|
cf455fc19b | ||
|
1bcddadb7a | ||
|
6dc28f11e0 | ||
|
8ad601fcc0 | ||
|
f400844a3d | ||
|
560096878f | ||
|
0938f5ab71 | ||
|
06193d27c0 | ||
|
eb18857ecc | ||
|
9a280e99ad | ||
|
c7ca20b45a | ||
|
60e64a3646 | ||
|
d60f89976e | ||
|
41e05ddf9c | ||
|
5a34f16dcf | ||
|
769ca4e26d | ||
|
b6e62b08e4 | ||
|
effe5b32fd | ||
|
9e38137e76 | ||
|
57c2e89f00 | ||
|
914a0bf514 | ||
|
210f5eabc9 | ||
|
5f5c91a8ff | ||
|
05c7121c8a | ||
|
551a8e9588 | ||
|
75fbdb653a | ||
|
bdfe75cff3 | ||
|
bcd845fd59 | ||
|
f1e71ecb78 | ||
|
0aa4c8af6f | ||
|
8fe5507ff8 | ||
|
a950b80d5a | ||
|
ed3bb6429b | ||
|
1e88491ca1 | ||
|
4aed647865 | ||
|
74ab7aaa3d | ||
|
dcf2055851 | ||
|
6b6ad05e3a | ||
|
734a4b5e00 | ||
|
da70fac0b6 | ||
|
5f4a364095 | ||
|
95a8867527 | ||
|
7cb1301e80 | ||
|
e6e070d89e | ||
|
ba2bcaba07 | ||
|
3d6ecba4f5 | ||
|
864f82ba11 | ||
|
f671c992e1 | ||
|
86220694ce | ||
|
77f31177c8 | ||
|
33ff91aea8 | ||
|
a4151800f1 | ||
|
932f24c966 | ||
|
0c0bce9755 | ||
|
f07508073f | ||
|
2c9cade70a | ||
|
e06cc1bd2d | ||
|
36e33a4c10 | ||
|
7f668c1653 | ||
|
b464fa98df | ||
|
23491f1e8c | ||
|
2b90a2eed2 | ||
|
13b9d15d8f | ||
|
a053504bb8 | ||
|
d7d7a84bd5 | ||
|
990463fbea | ||
|
dcdd4aec85 | ||
|
0d9a8ba6f7 | ||
|
179da2ac05 | ||
|
4848739b6e | ||
|
46da285831 | ||
|
71a6a36a54 | ||
|
c8ca9ef7ab | ||
|
5af2fff9ca | ||
|
edbaf3ac82 | ||
|
337c9bc01e | ||
|
cd84674ae0 | ||
|
a196dce1fa | ||
|
f60ea43f29 | ||
|
76f547a726 | ||
|
dffe5e0819 | ||
|
b9633bbcd6 | ||
|
46efe2b8dd | ||
|
fb9ef0c547 | ||
|
d52cd2b17c | ||
|
cefa80f317 | ||
|
cc1dd682e8 | ||
|
bdd984a887 | ||
|
2d3dffe5fc | ||
|
65f31a0b38 | ||
|
4a1a6c5933 | ||
|
7e1fd99c37 | ||
|
8fe8209580 | ||
|
264a050360 | ||
|
3623104e3b | ||
|
191ff1abec | ||
|
3bb86493cc | ||
|
d1d3151e1e | ||
|
f9dc9ebdb3 | ||
|
3b478bcc2d | ||
|
77bb78c381 | ||
|
cafa97f502 | ||
|
0d858493d5 | ||
|
99fb07c6b3 | ||
|
eaad971c0a | ||
|
377abd87fd | ||
|
af71176296 | ||
|
69737177ef | ||
|
efae1222c1 | ||
|
3caea1a903 | ||
|
a43478d627 | ||
|
ed2c3f43c7 | ||
|
84c9846f7b | ||
|
fcfd816cec | ||
|
2e3977e59c | ||
|
3c68430336 | ||
|
43afb86fa8 | ||
|
194ccbdbb4 | ||
|
7139e230cf | ||
|
120d3b9f54 | ||
|
712460a040 | ||
|
be5594f1c9 | ||
|
0a885117db | ||
|
5b73654544 | ||
|
1485b78b7b | ||
|
bfec57172a | ||
|
9f8559c12d | ||
|
83dde12ca9 | ||
|
d17888db4e | ||
|
096529af96 | ||
|
8a56b22635 | ||
|
dcdd353981 | ||
|
258564208b | ||
|
e2e8222005 | ||
|
75f2826805 | ||
|
730af4f2ee | ||
|
e5737ebd9d | ||
|
7f24904164 | ||
|
9ff7198602 | ||
|
6d56967a0f | ||
|
584118805a | ||
|
68b3f01082 | ||
|
77a82cb84b | ||
|
844b19495d | ||
|
b8b721f2bd | ||
|
4f93d48ac6 | ||
|
02d1bf5a2c | ||
|
fb3606c2b7 | ||
|
a5bc2cd48f | ||
|
72151ac6a3 | ||
|
e2c8b3bf02 | ||
|
06dd641274 | ||
|
7d9bf01d27 | ||
|
b9553e0a05 | ||
|
993dcaf235 | ||
|
8d7c39bac4 | ||
|
80933ab571 | ||
|
b5b30c8119 | ||
|
bca06129d9 | ||
|
a136b86d81 | ||
|
8d555d8ae7 | ||
|
c22e61add2 | ||
|
2c83f1ce57 | ||
|
f2750de153 | ||
|
e0934f11d6 | ||
|
422924026a | ||
|
332e22e534 | ||
|
c7bf30e18e | ||
|
5ade5176c0 | ||
|
f9e4fafe9f | ||
|
201f2ef1f0 | ||
|
32af4fdcca | ||
|
d254b4cc39 | ||
|
d0ad4e05bf | ||
|
c75854cb7b | ||
|
8cc71913b3 | ||
|
99abe6bcd2 | ||
|
f5ad7a49ce | ||
|
e42ecf3c99 | ||
|
b58bf9dc17 | ||
|
745c8aaf3e | ||
|
0ca73bf80b | ||
|
fd76cabd01 | ||
|
fcf9300a49 | ||
|
649b66ba1a | ||
|
b5d73a0861 | ||
|
1453996ccb | ||
|
5bf9b97d70 | ||
|
5c1e46f5a6 | ||
|
c2665cbae8 | ||
|
3934248a6b | ||
|
7ae3bb5601 | ||
|
9890d4f3bc | ||
|
5b47fc16d9 | ||
|
344770a0a4 | ||
|
fc11cacd24 | ||
|
737ebdd0c6 | ||
|
d06dddfa24 | ||
|
710d631ffe | ||
|
7d9a845ca0 | ||
|
cc6e5ffb97 | ||
|
8d29cb7488 | ||
|
5c588ea01a | ||
|
dade9935da | ||
|
34cd3aaaca | ||
|
78d3f338fb | ||
|
d801c5911e | ||
|
003743c074 | ||
|
4cef39d3b1 | ||
|
83f0df32d7 | ||
|
24f269191c | ||
|
94a0d5a0a4 | ||
|
c0fbf4dd0c | ||
|
37b6161075 | ||
|
c9b792c370 | ||
|
2103d547a1 | ||
|
3918e220d2 | ||
|
c3eaaed43b | ||
|
e0bf648076 | ||
|
bb298164e4 | ||
|
898694b9be | ||
|
f0f9ac92e6 | ||
|
ea0229a8ab | ||
|
66fc7cd91d | ||
|
c11d4f01b1 | ||
|
a8f498f292 | ||
|
6854e2275f | ||
|
6662e79ac5 | ||
|
9e77430634 | ||
|
b8e070824a | ||
|
304d4293f3 | ||
|
a03e7f5b53 | ||
|
ea57c8cad4 | ||
|
280802cf74 | ||
|
fbce01d846 | ||
|
591b60c336 | ||
|
78ef870d91 | ||
|
bc19d82aed | ||
|
79b41e1056 | ||
|
805f03d231 | ||
|
62acc1081f | ||
|
257a2c2d9f | ||
|
ed9b05cdf9 | ||
|
2cc6fbd643 | ||
|
bdfc260dd2 | ||
|
7ad65956c9 | ||
|
b3dc60b7ca | ||
|
bed08109fa | ||
|
06cedec090 | ||
|
1d2c468d03 | ||
|
e84616f5f5 | ||
|
caa9a90476 | ||
|
62be683dd8 | ||
|
ffa63b3f82 | ||
|
c5a7788394 | ||
|
99c42ff2c1 | ||
|
fd2b7bb917 | ||
|
922a494df0 | ||
|
c478ec0095 | ||
|
3abbe17910 | ||
|
349076599f | ||
|
92d299507f | ||
|
6f2d61e918 | ||
|
ed13babf6a | ||
|
80db82eb93 | ||
|
8d20334d6e | ||
|
03a95ad018 | ||
|
aa59cc8af0 | ||
|
80d63c2c89 | ||
|
03a4acd72b | ||
|
53118cf660 | ||
|
16b1baf81e | ||
|
960e0d0965 | ||
|
8f41222e43 | ||
|
e7bc447166 | ||
|
1736359615 | ||
|
58784b1e22 | ||
|
07f2bfd279 | ||
|
6d62db2890 | ||
|
a1b23c4aab | ||
|
e272a096da | ||
|
b8ca24c5bf | ||
|
a05d09f0de | ||
|
1807a79c4f | ||
|
77f6826af9 | ||
|
7e39eedf35 | ||
|
0b4b48ceae | ||
|
dad931e898 | ||
|
2e387730cb | ||
|
c9b6775793 | ||
|
a6eaf30c2b | ||
|
6f91d199d8 | ||
|
7ea486307a | ||
|
37d254c827 | ||
|
b4014eb317 | ||
|
c7824fa184 | ||
|
13c5bd45f9 | ||
|
465d102bd0 | ||
|
93007cd56c | ||
|
8367576dc8 | ||
|
dbc06145b3 | ||
|
4efcf0e7c8 | ||
|
0a4bbc1106 | ||
|
b08c1f6699 | ||
|
6828b905ef | ||
|
f72b405f6d | ||
|
27ae99864c | ||
|
82ba15ba5a | ||
|
af01db7bc9 | ||
|
6ec0a65d0c | ||
|
c32ccfc9ed | ||
|
ef818388c8 | ||
|
f5aa45a3e1 | ||
|
b7a047a743 | ||
|
05ec985453 | ||
|
88ed9c3e79 | ||
|
3fb03c8dfe | ||
|
ff304027cd | ||
|
3140d46c94 | ||
|
9d476af384 | ||
|
0d380672f3 | ||
|
e2fb8dca5b | ||
|
eaba4c90c5 | ||
|
b4ca7373f3 | ||
|
905c068ed5 | ||
|
02886dd420 | ||
|
5bf7754d6c | ||
|
7a0a3055c4 | ||
|
bf73efb3b4 | ||
|
b4da212158 | ||
|
4a04d42600 | ||
|
42bbfbe538 | ||
|
31ec2430c4 | ||
|
f0b56c9f1d | ||
|
6f9f01c991 | ||
|
b822ccb19d | ||
|
dcb11671f3 | ||
|
282599d36f | ||
|
f11acdc68f | ||
|
971e127cfd | ||
|
9b2c59d529 | ||
|
14dc049a66 | ||
|
d3d0e7c615 | ||
|
89423ccb8b | ||
|
746f31f70c | ||
|
3aa9eab2bd | ||
|
1bcc8fed5e | ||
|
1213a030e3 | ||
|
3b2344b477 | ||
|
c53b0fe2d4 | ||
|
0a92269456 | ||
|
1cb8906893 | ||
|
db05ff5e98 |
@ -1,34 +0,0 @@
|
||||
{
|
||||
"files": [
|
||||
"README.md"
|
||||
],
|
||||
"imageSize": 100,
|
||||
"commit": false,
|
||||
"contributors": [
|
||||
{
|
||||
"login": "antonioag95",
|
||||
"name": "antonioag95",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/30556866?v=4",
|
||||
"profile": "https://github.com/antonioag95",
|
||||
"contributions": [
|
||||
"test",
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "tonjo",
|
||||
"name": "tonjo",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/4726289?v=4",
|
||||
"profile": "https://github.com/tonjo",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
"projectName": "wireguard-dashboard",
|
||||
"projectOwner": "donaldzou",
|
||||
"repoType": "github",
|
||||
"repoHost": "https://github.com",
|
||||
"skipCi": true
|
||||
}
|
4
.github/FUNDING.yml
vendored
Normal file
4
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [donaldzou]
|
||||
patreon: DonaldDonnyZou
|
71
.github/workflows/codeql-analyze.yaml
vendored
Normal file
71
.github/workflows/codeql-analyze.yaml
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ main ]
|
||||
schedule:
|
||||
- cron: '30 5 * * 4'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'javascript', 'python' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||
# Learn more about CodeQL language support at https://git.io/codeql-language-support
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
105
.github/workflows/docker.yml
vendored
Normal file
105
.github/workflows/docker.yml
vendored
Normal file
@ -0,0 +1,105 @@
|
||||
name: Docker Build and Push
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
tags:
|
||||
- '*'
|
||||
release:
|
||||
types: [ published ]
|
||||
|
||||
env:
|
||||
DOCKERHUB_PREFIX: docker.io
|
||||
GITHUB_CONTAINER_PREFIX: ghcr.io
|
||||
DOCKER_IMAGE: donaldzou/wgdashboard
|
||||
|
||||
jobs:
|
||||
docker_build:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.DOCKERHUB_PREFIX }}
|
||||
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
|
||||
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.GITHUB_CONTAINER_PREFIX }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
with:
|
||||
platforms: |
|
||||
- linux/amd64
|
||||
- linux/arm64
|
||||
- linux/arm/v7
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Docker meta by docs https://github.com/docker/metadata-action
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: |
|
||||
${{ env.DOCKERHUB_PREFIX }}/${{ env.DOCKER_IMAGE }}
|
||||
${{ env.GITHUB_CONTAINER_PREFIX }}/${{ env.DOCKER_IMAGE }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
|
||||
- name: Build and export (multi-arch)
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: ./docker/Dockerfile
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||
|
||||
docker_scan:
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
runs-on: ubuntu-latest
|
||||
needs: docker_build
|
||||
steps:
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.DOCKERHUB_PREFIX }}
|
||||
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
|
||||
|
||||
- name: Docker Scout CVEs
|
||||
uses: docker/scout-action@v1
|
||||
with:
|
||||
command: cves
|
||||
image: ${{ env.GITHUB_CONTAINER_PREFIX }}/${{ env.DOCKER_IMAGE }}:main
|
||||
only-severities: critical,high
|
||||
only-fixed: true
|
||||
write-comment: true
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
exit-code: true
|
||||
|
||||
- name: Docker Scout Compare
|
||||
uses: docker/scout-action@v1
|
||||
with:
|
||||
command: compare
|
||||
# Set to Github for maximum compat
|
||||
image: ${{ env.GITHUB_CONTAINER_PREFIX }}/${{ env.DOCKER_IMAGE }}:main
|
||||
to: ${{ env.GITHUB_CONTAINER_PREFIX }}/${{ env.DOCKER_IMAGE }}:latest
|
||||
only-severities: critical,high
|
||||
ignore-unchanged: true
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
26
.github/workflows/stale.yml
vendored
Normal file
26
.github/workflows/stale.yml
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
# This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time.
|
||||
#
|
||||
# You can adjust the behavior by modifying this file.
|
||||
# For more information, see:
|
||||
# https://github.com/actions/stale
|
||||
name: Mark stale issues and pull requests
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '00 08 * * *'
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- uses: actions/stale@v9
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
stale-issue-message: 'This issue has not been updated for 20 days'
|
||||
stale-pr-message: 'This pull request has not been updated for 20 days'
|
||||
stale-issue-label: 'stale'
|
||||
exempt-issue-labels: 'enhancement,ongoing'
|
||||
days-before-stale: 20
|
55
.gitignore
vendored
55
.gitignore
vendored
@ -1,12 +1,53 @@
|
||||
.vscode/sftp.json
|
||||
src/.vscode/sftp.json
|
||||
.vscode
|
||||
.DS_Store
|
||||
wg.db
|
||||
*.json
|
||||
.idea
|
||||
src/test.py
|
||||
tmp
|
||||
src/db
|
||||
__pycache__
|
||||
src/wg-dashboard.ini
|
||||
src/test.py
|
||||
*.db
|
||||
src/wg-dashboard.ini
|
||||
src/static/pic.xd
|
||||
*.conf
|
||||
private_key.txt
|
||||
public_key.txt
|
||||
venv/**
|
||||
log/**
|
||||
release/*
|
||||
src/db/wgdashboard.db
|
||||
.jshintrc
|
||||
node_modules/**
|
||||
*/proxy.js
|
||||
src/static/app/proxy.js
|
||||
.secrets
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist-ssr
|
||||
coverage
|
||||
*.local
|
||||
|
||||
/cypress/videos/
|
||||
/cypress/screenshots/
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
*.tsbuildinfo
|
||||
.vite/*
|
||||
|
||||
|
267
README.md
267
README.md
@ -1,202 +1,87 @@
|
||||
<hr>
|
||||
<p align=center>I'm looking for someone that have experiences on migrating this project to a Docker app, with a complete solution ;) If you know how please <a href="https://github.com/donaldzou/wireguard-dashboard/issues/20">comment in here</a>.</p>
|
||||
<hr>
|
||||
> [!TIP]
|
||||
> 🎉 I'm excited to announce that WGDashboard is officially listed on DigitalOcean's Marketplace! For more information, please visit [Host WGDashboard & WireGuard with DigitalOcean](https://donaldzou.dev/WGDashboard-Documentation/host-wgdashboard-wireguard-with-digitalocean.html) for more information!
|
||||
|
||||
> [!NOTE]
|
||||
> **Help Wanted 🎉**: Localizing WGDashboard to other languages! If you're willing to help, please visit https://github.com/donaldzou/WGDashboard/issues/397. Many thanks!
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
<p align="center">
|
||||
<img src="https://raw.githubusercontent.com/donaldzou/wireguard-dashboard/main/img/Group%202.png" width="128">
|
||||
<img alt="WGDashboard" src="https://wgdashboard-resources.tor1.cdn.digitaloceanspaces.com/Logos/Logo-2-Rounded-512x512.png" width="128">
|
||||
</p>
|
||||
<h1 align="center">
|
||||
<a href="https://wgdashboard.dev">WGDashboard</a>
|
||||
</h1>
|
||||
<p align="center">
|
||||
<img src="https://img.shields.io/badge/Made_With-Python-blue?style=for-the-badge&logo=python&logoColor=ffffff">
|
||||
<img src="https://img.shields.io/badge/Made_With-Vue.js-42b883?style=for-the-badge&logo=vuedotjs&logoColor=ffffff">
|
||||
<img src="https://img.shields.io/badge/License-Apache_License_2.0-D22128?style=for-the-badge&logo=apache&logoColor=ffffff">
|
||||
</p>
|
||||
<h1 align="center"> Wireguard Dashboard</h1>
|
||||
|
||||
<p align="center">
|
||||
<img src="http://ForTheBadge.com/images/badges/made-with-python.svg">
|
||||
<a href="https://github.com/donaldzou/wireguard-dashboard/releases/latest"><img src="https://img.shields.io/github/v/release/donaldzou/wireguard-dashboard?style=for-the-badge"></a>
|
||||
<a href="https://wakatime.com/badge/github/donaldzou/WGDashboard"><img src="https://wakatime.com/badge/github/donaldzou/WGDashboard.svg?style=for-the-badge" alt="wakatime"></a>
|
||||
<a href="https://hitscounter.dev"><img src="https://hitscounter.dev/api/hit?url=https%3A%2F%2Fgithub.com%2Fdonaldzou%2FWGDashboard&label=Visitor&icon=github&color=%230a58ca&style=for-the-badge"></a>
|
||||
<img src="https://img.shields.io/docker/pulls/donaldzou/wgdashboard?logo=docker&label=Docker%20Image%20Pulls&labelColor=ffffff&style=for-the-badge">
|
||||
</p>
|
||||
<p align="center"><b>This project is supported by</b></p>
|
||||
<p align="center">
|
||||
<a href="https://m.do.co/c/a84cb9aac585">
|
||||
<img src="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_blue.svg" width="201px">
|
||||
</a>
|
||||
</p>
|
||||
<p align="center">Monitoring WireGuard is not convenient, in most case, you'll need to login to your server and type <code>wg show</code>. That's why this project is being created, to view and manage all WireGuard configurations in a easy way.</p>
|
||||
<p align="center">With all these awesome features, while keeping it <b>easy to install and use</b></p>
|
||||
|
||||
<p align="center"><b><i>This project is not affiliate to the official WireGuard Project</i></b></p>
|
||||
|
||||
<h3 align="center">Looking for help or want to chat about this project?</h4>
|
||||
<p align="center">
|
||||
You can reach out at
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://github.com/donaldzou/wireguard-dashboard/releases/latest"><img src="https://img.shields.io/github/v/release/donaldzou/wireguard-dashboard"></a>
|
||||
<a align="center" href="https://discord.gg/72TwzjeuWm" target="_blank"><img src="https://img.shields.io/discord/1276818723637956628?labelColor=ffffff&style=for-the-badge&logo=discord&label=Discord"></a>
|
||||
<a align="center" href="https://www.reddit.com/r/WGDashboard/" target="_blank"><img src="https://img.shields.io/badge/Reddit-r%2FWGDashboard-FF4500?style=for-the-badge&logo=reddit"></a>
|
||||
<a align="center" href="https://app.element.io/#/room/#wgd:matrix.org" target="_blank"><img src="https://img.shields.io/badge/Matrix_Chatroom-%23WGD-000000?style=for-the-badge&logo=matrix"></a>
|
||||
</p>
|
||||
<h3 align="center">Want to support this project?</h4>
|
||||
<p align="center">
|
||||
You can support via <br>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a align="center" href="https://github.com/sponsors/donaldzou" target="_blank"><img src="https://img.shields.io/badge/GitHub%20Sponsor-2e9a40?style=for-the-badge&logo=github"></a>
|
||||
<a align="center" href="https://buymeacoffee.com/donaldzou" target="_blank"><img src="https://img.shields.io/badge/Buy%20me%20a%20coffee-ffdd00?style=for-the-badge&logo=buymeacoffee&logoColor=000000"></a>
|
||||
<a align="center" href="https://patreon.com/c/DonaldDonnyZou/membership" target="_blank"><img src="https://img.shields.io/badge/Patreon-000000?style=for-the-badge&logo=patreon&logoColor=ffffff"></a>
|
||||
</p>
|
||||
<p align="center">Monitoring WireGuard is not convinient, need to login into server and type <code>wg show</code>. That's why this platform is being created, to view all configurations and manage them in a easier way.</p>
|
||||
|
||||
|
||||
|
||||
## 📣 What's New: Version 2.0.1
|
||||
|
||||
|
||||
- Added **Ping** and **Traceroute** tool
|
||||
- Adjusted the calculation of data usage on each peers
|
||||
- Added refresh interval of the dashboard
|
||||
<p align="center">
|
||||
<b>or, visit our merch store and support us by purchasing a merch for only $USD 17.00 (Including shipping worldwide & duties)</b>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a align="center" href="https://merch.wgdashboard.dev" target="_blank"><img src="https://img.shields.io/badge/Merch%20from%20WGDashboard-926183?style=for-the-badge"></a>
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
|
||||
### ⚠️ **Update from v1.x.x**
|
||||
|
||||
1. Stop the dashboard if it is running.
|
||||
2. You can use `git pull https://github.com/donaldzou/Wireguard-Dashboard.git v2.0.1` to get the new update inside `Wireguard-Dashboard` directory.
|
||||
3. Proceed **Step 2 & 3** in the [Install](#-install) step down below.
|
||||
|
||||
|
||||
|
||||
## 💡 Features
|
||||
|
||||
- Add peers for each WireGuard configuration
|
||||
|
||||
- Manage peer
|
||||
|
||||
- Delete peers
|
||||
|
||||
- And many more coming up! Welcome to contribute to this project!
|
||||
|
||||
|
||||
|
||||
## 📝 Requirement
|
||||
|
||||
- Ubuntu or Debian based OS, other might work, but haven't test yet. Tested on the following OS:
|
||||
- [x] Ubuntu 18.04.1 LTS
|
||||
- [ ] If you have tested on other OS and it works perfectly please provide it to me!
|
||||
|
||||
- ‼️ Make sure you have **Wireguard** and **Wireguard-Tools (`wg-quick`)** installed.‼️ <a href="https://www.wireguard.com/install/">How to install?</a>
|
||||
- Configuration files under **/etc/wireguard**
|
||||
|
||||
- **Note: For peers, `PublicKey` & `AllowedIPs` is required.**
|
||||
- Python 3.7+ & Pip3
|
||||
|
||||
|
||||
|
||||
## 🛠 Install
|
||||
|
||||
**1. Download Wireguard Dashboard**
|
||||
|
||||
```shell
|
||||
git clone -b v2.0.1 https://github.com/donaldzou/Wireguard-Dashboard.git
|
||||
```
|
||||
|
||||
**2. Install Python Dependencies**
|
||||
|
||||
```shell
|
||||
cd Wireguard-Dashboard/src
|
||||
python3 -m pip install -r requirements.txt
|
||||
```
|
||||
|
||||
**3. Install & run Wireguard Dashboard**
|
||||
|
||||
```shell
|
||||
chmod u+x wgd.sh
|
||||
./wgd.sh start
|
||||
```
|
||||
|
||||
Access your server with port `10086` ! e.g (http://your_server_ip:10086), continue to read to on how to change port and ip that dashboard is running with.
|
||||
|
||||
|
||||
|
||||
## 🪜 Usage
|
||||
|
||||
**1. Start/Stop/Restart Wireguard Dashboard**
|
||||
|
||||
```shell
|
||||
cd Wireguard-Dashboard/src
|
||||
./wgd.sh start # Start the dashboard in background
|
||||
./wgd.sh debug # Start the dashboard in foreground (debug mode)
|
||||
./wgd.sh stop # Stop the dashboard
|
||||
./wgd.sh restart # Restart the dasboard
|
||||
./wgd.sh update # Update the dashboard
|
||||
```
|
||||
|
||||
⚠️ **For first time user please also read the next section.**
|
||||
|
||||
|
||||
|
||||
## ✂️ Dashboard Configuration
|
||||
|
||||
Since version 2.0, Wireguard Dashboard will be using a configuration file called `wg-dashboard.ini`, (It will generate automatically after first time running the dashboard). More options will include in future versions, and for now it included the following config:
|
||||
|
||||
### `[Account]`
|
||||
|
||||
`username` - Username (Default: `admin`)
|
||||
|
||||
`password` - Password, will be hash with SHA256 (Default: `admin`).
|
||||
|
||||
### `[Server]`
|
||||
|
||||
`wg_conf_path` - The path of all the Wireguard configurations (Default: `/etc/wireguard`)
|
||||
|
||||
`app_ip` - IP address the flask will run with (Default: `0.0.0.0`)
|
||||
|
||||
`app_port` - Port the flask will run with (Default: `10086`)
|
||||
|
||||
`auth_req` - Does the dashboard need authentication (Default: `true`)
|
||||
|
||||
- If `auth_req = false` , user will not be access the **Setting** tab due to security consideration. **User can only change the file directly in system**.
|
||||
|
||||
`version` - Dashboard Version
|
||||
|
||||
All these settings will be able to configure within the dashboard in **Settings** on the sidebar, without changing the actual file. **Except `version` and `auth_req` due to security consideration.**
|
||||
|
||||
|
||||
|
||||
## ❓ How to update the dashboard?
|
||||
|
||||
```shell
|
||||
cd wireguard-dashboard
|
||||
sudo sh wgd.sh update # Perform update
|
||||
sudo sh wgd.sh start # Start dashboard
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 🔍 Screenshot
|
||||
|
||||

|
||||
|
||||
<p align=center>Index Page</p>
|
||||
|
||||

|
||||
|
||||
<p align=center>Signin Page</p>
|
||||
|
||||

|
||||
|
||||
<p align=center>Configuration Page</p>
|
||||
|
||||

|
||||
|
||||
<p align=center>Settings Page</p>
|
||||
|
||||
|
||||
|
||||
## 🛒 Dependencies
|
||||
|
||||
- CSS/JS
|
||||
- [Bootstrap](https://getbootstrap.com/docs/4.6/getting-started/introduction/) `v4.6.0`
|
||||
- [Bootstrap Icon](https://icons.getbootstrap.com) `v1.4.0`
|
||||
- [jQuery](https://jquery.com) `v3.5.1`
|
||||
- Python
|
||||
- [Flask](https://pypi.org/project/Flask/) `v1.1.2`
|
||||
- [TinyDB](https://pypi.org/project/tinydb/) `v4.3.0`
|
||||
- [ifcfg](https://pypi.org/project/ifcfg/) `v0.21`
|
||||
- [icmplib](https://pypi.org/project/icmplib/) `v2.1.1`
|
||||
|
||||
|
||||
|
||||
## Contributors ✨
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
||||
[](#contributors-)
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
||||
|
||||
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
||||
<!-- prettier-ignore-start -->
|
||||
<!-- markdownlint-disable -->
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/antonioag95"><img src="https://avatars.githubusercontent.com/u/30556866?v=4?s=100" width="100px;" alt=""/><br /><sub><b>antonioag95</b></sub></a><br /><a href="https://github.com/donaldzou/wireguard-dashboard/commits?author=antonioag95" title="Tests">⚠️</a> <a href="https://github.com/donaldzou/wireguard-dashboard/commits?author=antonioag95" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/tonjo"><img src="https://avatars.githubusercontent.com/u/4726289?v=4?s=100" width="100px;" alt=""/><br /><sub><b>tonjo</b></sub></a><br /><a href="https://github.com/donaldzou/wireguard-dashboard/commits?author=tonjo" title="Code">💻</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- markdownlint-restore -->
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
|
||||
|
||||
<h4 align="center">
|
||||
for more information, visit our
|
||||
</h4>
|
||||
<h1 align="center">
|
||||
<a href="https://wgdashboard.dev">Official Website</a>
|
||||
</h1>
|
||||
|
||||
|
||||
# Screenshots
|
||||
|
||||
<img src="https://wgdashboard-resources.tor1.cdn.digitaloceanspaces.com/Documentation%20Images/sign-in.png" alt=""/>
|
||||
<img src="https://wgdashboard-resources.tor1.cdn.digitaloceanspaces.com/Documentation%20Images/cross-server.png" alt=""/>
|
||||
<img src="https://wgdashboard-resources.tor1.cdn.digitaloceanspaces.com/Documentation%20Images/index.png" alt=""/>
|
||||
<img src="https://wgdashboard-resources.tor1.cdn.digitaloceanspaces.com/Documentation%20Images/new-configuration.png" alt="" />
|
||||
<img src="https://wgdashboard-resources.tor1.cdn.digitaloceanspaces.com/Documentation%20Images/settings.png" alt="" />
|
||||
<img src="https://wgdashboard-resources.tor1.cdn.digitaloceanspaces.com/Documentation%20Images/light-dark.png" alt="" />
|
||||
<img src="https://wgdashboard-resources.tor1.cdn.digitaloceanspaces.com/Documentation%20Images/configuration.png" alt=""/>
|
||||
<img src="https://wgdashboard-resources.tor1.cdn.digitaloceanspaces.com/Documentation%20Images/add-peers.png" alt="" />
|
||||
<img src="https://wgdashboard-resources.tor1.cdn.digitaloceanspaces.com/Documentation%20Images/ping.png" alt=""/>
|
||||
<img src="https://wgdashboard-resources.tor1.cdn.digitaloceanspaces.com/Documentation%20Images/traceroute.png" alt=""/>
|
||||
|
10
SECURITY.md
Normal file
10
SECURITY.md
Normal file
@ -0,0 +1,10 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 5.1.x | :white_check_mark: |
|
||||
| 5.0.x | :x: |
|
||||
| 4.0.x | :white_check_mark: |
|
||||
| < 4.0 | :x: |
|
70
docker/Dockerfile
Normal file
70
docker/Dockerfile
Normal file
@ -0,0 +1,70 @@
|
||||
FROM golang:1.24 AS awg
|
||||
|
||||
RUN git clone https://github.com/amnezia-vpn/amneziawg-go /awg
|
||||
WORKDIR /awg
|
||||
RUN go mod download && \
|
||||
go mod verify && \
|
||||
go build -ldflags '-linkmode external -extldflags "-fno-PIC -static"' -v -o /usr/bin
|
||||
|
||||
FROM alpine:latest
|
||||
LABEL maintainer="dselen@nerthus.nl"
|
||||
|
||||
RUN apk update && apk add \
|
||||
iproute2 iptables bash curl wget unzip procps sudo \
|
||||
tzdata wireguard-tools python3 py3-psutil py3-bcrypt openresolv \
|
||||
&& cd /usr/bin/ \
|
||||
&& wget $(curl -s https://api.github.com/repos/amnezia-vpn/amneziawg-tools/releases/latest | grep 'alpine' | cut -d : -f 2,3 | tr -d '", ' | tail -n 1) \
|
||||
&& unzip -j alpine-3.19-amneziawg-tools.zip \
|
||||
&& chmod +x /usr/bin/awg /usr/bin/awg-quick \
|
||||
&& rm alpine-3.19-amneziawg-tools.zip
|
||||
|
||||
COPY --from=awg /usr/bin/amneziawg-go /usr/bin/amneziawg-go
|
||||
|
||||
# Declaring environment variables, change Peernet to an address you like, standard is a 24 bit subnet.
|
||||
ARG wg_net="10.0.0.1" \
|
||||
wg_port="51820"
|
||||
|
||||
# Following ENV variables are changable on container runtime because /entrypoint.sh handles that. See compose.yaml for more info.
|
||||
ENV TZ="Europe/Amsterdam" \
|
||||
global_dns="9.9.9.9" \
|
||||
wgd_port="10086" \
|
||||
public_ip=""
|
||||
|
||||
# Using WGDASH -- like wg_net functionally as a ARG command. But it is needed in entrypoint.sh so it needs to be exported as environment variable.
|
||||
ENV WGDASH=/opt/wgdashboard
|
||||
|
||||
# Doing WireGuard Dashboard installation measures. Modify the git clone command to get the preferred version, with a specific branch for example.
|
||||
RUN mkdir /data \
|
||||
&& mkdir /configs \
|
||||
&& mkdir -p ${WGDASH}/src \
|
||||
&& mkdir -p /etc/amnezia/amneziawg
|
||||
COPY ./src ${WGDASH}/src
|
||||
|
||||
# Generate basic WireGuard interface. Echoing the WireGuard interface config for readability, adjust if you want it for efficiency.
|
||||
# Also setting the pipefail option, verbose: https://github.com/hadolint/hadolint/wiki/DL4006.
|
||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||
RUN out_adapt=$(ip -o -4 route show to default | awk '{print $NF}') \
|
||||
&& echo -e "[Interface]\n\
|
||||
Address = ${wg_net}/24\n\
|
||||
PrivateKey =\n\
|
||||
PostUp = iptables -t nat -I POSTROUTING 1 -s ${wg_net}/24 -o ${out_adapt} -j MASQUERADE\n\
|
||||
PostUp = iptables -I FORWARD -i wg0 -o wg0 -j DROP\n\
|
||||
PreDown = iptables -t nat -D POSTROUTING -s ${wg_net}/24 -o ${out_adapt} -j MASQUERADE\n\
|
||||
PreDown = iptables -D FORWARD -i wg0 -o wg0 -j DROP\n\
|
||||
ListenPort = ${wg_port}\n\
|
||||
SaveConfig = true\n\
|
||||
DNS = ${global_dns}" > /configs/wg0.conf.template \
|
||||
&& chmod 600 /configs/wg0.conf.template
|
||||
|
||||
# Defining a way for Docker to check the health of the container. In this case: checking the gunicorn process.
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||
CMD sh -c 'pgrep gunicorn > /dev/null && pgrep tail > /dev/null' || exit 1
|
||||
|
||||
# Copy the basic entrypoint.sh script.
|
||||
COPY ./docker/entrypoint.sh /entrypoint.sh
|
||||
|
||||
# Exposing the default WireGuard Dashboard port for web access.
|
||||
EXPOSE 10086
|
||||
WORKDIR $WGDASH
|
||||
|
||||
ENTRYPOINT ["/bin/bash", "/entrypoint.sh"]
|
197
docker/README.md
Normal file
197
docker/README.md
Normal file
@ -0,0 +1,197 @@
|
||||
# WGDashboard Docker Explanation:
|
||||
Author: @DaanSelen<br>
|
||||
|
||||
This document delves into how the WGDashboard Docker container has been built.<br>
|
||||
Of course there are two stages (simply said), one before run-time and one at/after run-time.<br>
|
||||
The `Dockerfile` describes how the container image is made, and the `entrypoint.sh` is executed after running the container. <br>
|
||||
In this example, WireGuard is integrated into the container itself, so it should be a run-and-go(/out-of-the-box).<br>
|
||||
For more details on the source-code specific to this Docker image, refer to the source files, they have lots of comments.
|
||||
|
||||
<br>
|
||||
<img
|
||||
src="https://wgdashboard-resources.tor1.cdn.digitaloceanspaces.com/Logos/Logo-2-Rounded-512x512.png"
|
||||
alt="WG-Dashboard Logo"
|
||||
title="WG-Dashboard Logo"
|
||||
style="display: block; margin: 0 auto;"
|
||||
width="150"
|
||||
height="150"
|
||||
/>
|
||||
<br>
|
||||
|
||||
To get the container running you either pull the image from the repository, (docker.io)`donaldzou/wgdashboard:latest`.<br>
|
||||
From there either use the environment variables describe below as parameters or use the Docker Compose file: `compose.yaml`.<br>
|
||||
Be careful, the default generated WireGuard configuration file uses port 51820/udp. So use this port if you want to use it out of the box.<br>
|
||||
Otherwise edit the configuration file in `/etc/wireguard/wg0.conf`.
|
||||
|
||||
# WGDashboard: 🐳 Docker Deployment Guide
|
||||
|
||||
To run the container, you can either pull the image from Docker Hub or build it yourself. The image is available at:
|
||||
|
||||
```
|
||||
docker.io/donaldzou/wgdashboard:latest
|
||||
```
|
||||
|
||||
> `docker.io` is in most cases automatically resolved by the Docker application.
|
||||
|
||||
### 🔧 Quick Docker Run Command
|
||||
|
||||
Here's an example to get it up and running quickly:
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
--name wgdashboard \
|
||||
--restart unless-stopped \
|
||||
-p 10086:10086/tcp \
|
||||
-p 51820:51820/udp \
|
||||
--cap-add NET_ADMIN \
|
||||
donaldzou/wgdashboard:latest
|
||||
```
|
||||
|
||||
> ⚠️ The default WireGuard port is `51820/udp`. If you change this, update the `/etc/wireguard/wg0.conf` accordingly.
|
||||
|
||||
---
|
||||
|
||||
### 📦 Docker Compose Alternative
|
||||
|
||||
You can also use Docker Compose for easier configuration:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
wgdashboard:
|
||||
image: donaldzou/wgdashboard:latest
|
||||
restart: unless-stopped
|
||||
container_name: wgdashboard
|
||||
environment:
|
||||
# - tz=Europe/Amsterdam
|
||||
# - global_dns=1.1.1.1
|
||||
# - public_ip=YOUR_PUBLIC_IP
|
||||
ports:
|
||||
- 10086:10086/tcp
|
||||
- 51820:51820/udp
|
||||
volumes:
|
||||
- conf:/etc/wireguard
|
||||
- data:/data
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
|
||||
volumes:
|
||||
conf:
|
||||
data:
|
||||
```
|
||||
|
||||
> 📁 You can customize the **volume paths** on the host to fit your needs. The example above uses Docker volumes.
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Updating the Container
|
||||
|
||||
Updating WGDashboard is currently in **alpha** stage. While the update process may work, it's still under testing.
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ Environment Variables
|
||||
|
||||
| Variable | Accepted Values | Default | Example | Description |
|
||||
|---------------|------------------------------------------|-------------------------|------------------------|-----------------------------------------------------------------------------|
|
||||
| `tz` | Timezone | `Europe/Amsterdam` | `America/New_York` | Sets the container's timezone. Useful for accurate logs and scheduling. |
|
||||
| `global_dns` | IPv4 and IPv6 addresses | `9.9.9.9` | `8.8.8.8`, `1.1.1.1` | Default DNS for WireGuard clients. |
|
||||
| `public_ip` | Public IP address | Retrieved automatically | `253.162.134.73` | Used to generate accurate client configs. Needed if container is NAT’d. |
|
||||
| `wgd_port` | Any port that is allowed for the process | `10086` | `443` | This port is used to set the WGDashboard web port. |
|
||||
|
||||
---
|
||||
|
||||
## 🔐 Port Forwarding Note
|
||||
|
||||
When using multiple WireGuard interfaces, remember to **open their respective ports** on the host.
|
||||
|
||||
Examples:
|
||||
```yaml
|
||||
# Individual mapping
|
||||
- 51821:51821/udp
|
||||
|
||||
# Or port range
|
||||
- 51820-51830:51820-51830/udp
|
||||
```
|
||||
|
||||
> 🚨 **Security Tip:** Only expose ports you actually use.
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Building the Image Yourself
|
||||
|
||||
To build from source:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/donaldzou/WGDashboard.git
|
||||
cd WGDashboard
|
||||
docker build . -f docker/Dockerfile -t yourname/wgdashboard:latest
|
||||
```
|
||||
|
||||
Example output:
|
||||
```shell
|
||||
docker images
|
||||
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
yourname/wgdashboard latest c96fd96ee3b3 42 minutes ago 314MB
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧱 Dockerfile Overview
|
||||
|
||||
Here's a brief overview of the Dockerfile stages used in the image build:
|
||||
|
||||
### 1. **Build Tools & Go Compilation**
|
||||
|
||||
```Dockerfile
|
||||
FROM golang:1.24 AS compiler
|
||||
WORKDIR /go
|
||||
|
||||
RUN apt-get update && apt-get install -y ...
|
||||
RUN git clone ... && make
|
||||
...
|
||||
```
|
||||
|
||||
### 2. **Binary Copy to Scratch**
|
||||
|
||||
```Dockerfile
|
||||
FROM scratch AS bins
|
||||
COPY --from=compiler /go/amneziawg-go/amneziawg-go /amneziawg-go
|
||||
...
|
||||
```
|
||||
|
||||
### 3. **Final Alpine Container Setup**
|
||||
|
||||
```Dockerfile
|
||||
FROM alpine:latest
|
||||
COPY --from=bins ...
|
||||
RUN apk update && apk add --no-cache ...
|
||||
COPY ./src ${WGDASH}/src
|
||||
COPY ./docker/entrypoint.sh /entrypoint.sh
|
||||
...
|
||||
EXPOSE 10086
|
||||
ENTRYPOINT ["/bin/bash", "/entrypoint.sh"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Entrypoint Overview
|
||||
|
||||
### Major Functions:
|
||||
|
||||
- **`ensure_installation`**: Sets up the app, database, and Python environment.
|
||||
- **`set_envvars`**: Writes `wg-dashboard.ini` and applies environment variables.
|
||||
- **`start_core`**: Starts the main WGDashboard service.
|
||||
- **`ensure_blocking`**: Tails the error log to keep the container process alive.
|
||||
|
||||
---
|
||||
|
||||
## ✅ Final Notes
|
||||
|
||||
- Use `docker logs wgdashboard` for troubleshooting.
|
||||
- Access the web interface via `http://your-ip:10086` (or whichever port you specified in the compose).
|
||||
- The first time run will auto-generate WireGuard keys and configs (configs are generated from the template).
|
||||
|
||||
## Closing remarks:
|
||||
|
||||
For feedback please submit an issue to the repository. Or message dselen@nerthus.nl.
|
23
docker/compose.yaml
Normal file
23
docker/compose.yaml
Normal file
@ -0,0 +1,23 @@
|
||||
services:
|
||||
wireguard-dashboard:
|
||||
image: donaldzou/wgdashboard:latest
|
||||
restart: unless-stopped
|
||||
container_name: wgdashboard
|
||||
#environment:
|
||||
#- tz= # <--- Set container timezone, default: Europe/Amsterdam.
|
||||
#- public_ip= # <--- Set public IP to ensure the correct one is chosen, defaulting to the IP give by ifconfig.me.
|
||||
#- wgd_port= # <--- Set the port WGDashboard will use for its web-server.
|
||||
ports:
|
||||
- 10086:10086/tcp
|
||||
- 51820:51820/udp
|
||||
volumes:
|
||||
- aconf:/etc/amnezia/amneziawg
|
||||
- conf:/etc/wireguard
|
||||
- data:/data
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
|
||||
volumes:
|
||||
aconf:
|
||||
conf:
|
||||
data:
|
189
docker/entrypoint.sh
Normal file
189
docker/entrypoint.sh
Normal file
@ -0,0 +1,189 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Path to the configuration file (exists because of previous function).
|
||||
config_file="/data/wg-dashboard.ini"
|
||||
|
||||
trap 'stop_service' SIGTERM
|
||||
|
||||
stop_service() {
|
||||
echo "[WGDashboard] Stopping WGDashboard..."
|
||||
/bin/bash ./wgd.sh stop
|
||||
exit 0
|
||||
}
|
||||
|
||||
echo "------------------------- START ----------------------------"
|
||||
echo "Starting the WireGuard Dashboard Docker container."
|
||||
|
||||
ensure_installation() {
|
||||
# When using a custom directory to store the files, this part moves over and makes sure the installation continues.
|
||||
echo "Quick-installing..."
|
||||
|
||||
# Make the wgd.sh script executable.
|
||||
chmod +x "${WGDASH}"/src/wgd.sh
|
||||
cd "${WGDASH}"/src || exit
|
||||
|
||||
# Github issue: https://github.com/donaldzou/WGDashboard/issues/723
|
||||
echo "Checking for stale pids..."
|
||||
if [[ -f ${WGDASH}/src/gunicorn.pid ]]; then
|
||||
echo "Found stale pid, removing..."
|
||||
rm ${WGDASH}/src/gunicorn.pid
|
||||
fi
|
||||
|
||||
# Removing clear shell command from the wgd.sh script to enhance docker logging.
|
||||
echo "Removing clear command from wgd.sh for better Docker logging."
|
||||
sed -i '/clear/d' ./wgd.sh
|
||||
|
||||
# Create the databases directory if it does not exist yet.
|
||||
if [ ! -d "/data/db" ]; then
|
||||
echo "Creating database dir"
|
||||
mkdir /data/db
|
||||
fi
|
||||
|
||||
# Linking the database on the persistent directory location to where WGDashboard expects.
|
||||
if [ ! -d "${WGDASH}/src/db" ]; then
|
||||
ln -s /data/db "${WGDASH}/src/db"
|
||||
fi
|
||||
|
||||
# Create the wg-dashboard.ini file if it does not exist yet.
|
||||
if [ ! -f "${config_file}" ]; then
|
||||
echo "Creating wg-dashboard.ini file"
|
||||
touch "${config_file}"
|
||||
fi
|
||||
|
||||
# Link the wg-dashboard.ini file from the persistent directory to where WGDashboard expects it.
|
||||
if [ ! -f "${WGDASH}/src/wg-dashboard.ini" ]; then
|
||||
ln -s "${config_file}" "${WGDASH}/src/wg-dashboard.ini"
|
||||
fi
|
||||
|
||||
# Create the Python virtual environment.
|
||||
python3 -m venv "${WGDASH}"/src/venv
|
||||
. "${WGDASH}/src/venv/bin/activate"
|
||||
|
||||
# Due to this pip dependency being available as a system package we can just move it to the venv.
|
||||
echo "Moving PIP dependency from ephemerality to runtime environment: psutil"
|
||||
mv /usr/lib/python3.12/site-packages/psutil* "${WGDASH}"/src/venv/lib/python3.12/site-packages
|
||||
|
||||
# Due to this pip dependency being available as a system package we can just move it to the venv.
|
||||
echo "Moving PIP dependency from ephemerality to runtime environment: bcrypt"
|
||||
mv /usr/lib/python3.12/site-packages/bcrypt* "${WGDASH}"/src/venv/lib/python3.12/site-packages
|
||||
|
||||
# Use the bash interpreter to install WGDashboard according to the wgd.sh script.
|
||||
/bin/bash ./wgd.sh install
|
||||
|
||||
echo "Looks like the installation succeeded. Moving on."
|
||||
|
||||
# This first step is to ensure the wg0.conf file exists, and if not, then its copied over from the ephemeral container storage.
|
||||
# This is done so WGDashboard it works out of the box, it also sets a randomly generated private key.
|
||||
|
||||
if [ ! -f "/etc/wireguard/wg0.conf" ]; then
|
||||
echo "Standard wg0 Configuration file not found, grabbing template."
|
||||
cp -a "/configs/wg0.conf.template" "/etc/wireguard/wg0.conf"
|
||||
|
||||
echo "Setting a secure private key."
|
||||
|
||||
local privateKey
|
||||
privateKey=$(wg genkey)
|
||||
sed -i "s|^PrivateKey *=.*$|PrivateKey = ${privateKey}|g" /etc/wireguard/wg0.conf
|
||||
|
||||
echo "Done setting template."
|
||||
else
|
||||
echo "Existing wg0 configuration file found, using that."
|
||||
fi
|
||||
}
|
||||
|
||||
set_envvars() {
|
||||
printf "\n------------- SETTING ENVIRONMENT VARIABLES ----------------\n"
|
||||
|
||||
# Check if the file is empty
|
||||
if [ ! -s "${config_file}" ]; then
|
||||
echo "Config file is empty. Creating [Peers] section."
|
||||
|
||||
# Create [Peers] section with initial values
|
||||
{
|
||||
echo "[Peers]"
|
||||
echo "peer_global_dns = ${global_dns}"
|
||||
echo "remote_endpoint = ${public_ip}"
|
||||
echo -e "\n[Server]"
|
||||
echo "app_port = ${wgd_port}"
|
||||
} > "${config_file}"
|
||||
|
||||
else
|
||||
echo "Config file is not empty, using pre-existing."
|
||||
fi
|
||||
|
||||
echo "Verifying current variables..."
|
||||
|
||||
# Check and update the DNS if it has changed
|
||||
current_dns=$(grep "peer_global_dns = " "${config_file}" | awk '{print $NF}')
|
||||
if [ "${global_dns}" == "$current_dns" ]; then
|
||||
echo "DNS is set correctly, moving on."
|
||||
|
||||
else
|
||||
echo "Changing default DNS..."
|
||||
sed -i "s/^peer_global_dns = .*/peer_global_dns = ${global_dns}/" "${config_file}"
|
||||
fi
|
||||
|
||||
# Checking the current set public IP and changing it if it has changed.
|
||||
current_public_ip=$(grep "remote_endpoint = " "${config_file}" | awk '{print $NF}')
|
||||
if [ "${public_ip}" == "" ]; then
|
||||
default_ip=$(curl -s ifconfig.me)
|
||||
|
||||
echo "Trying to fetch the Public-IP using ifconfig.me: ${default_ip}"
|
||||
sed -i "s/^remote_endpoint = .*/remote_endpoint = ${default_ip}/" "${config_file}"
|
||||
elif [ "${current_public_ip}" != "${public_ip}" ]; then
|
||||
sed -i "s/^remote_endpoint = .*/remote_endpoint = ${public_ip}/" "${config_file}"
|
||||
else
|
||||
echo "Public-IP is correct, moving on."
|
||||
fi
|
||||
|
||||
# Checking the current WGDashboard web port and changing if needed.
|
||||
current_wgd_port=$(grep "app_port = " "${config_file}" | awk '{print $NF}')
|
||||
if [ "${current_wgd_port}" == "${wgd_port}" ]; then
|
||||
echo "Current WGD port is set correctly, moving on."
|
||||
else
|
||||
echo "Changing default WGD port..."
|
||||
sed -i "s/^app_port = .*/app_port = ${wgd_port}/" "${config_file}"
|
||||
fi
|
||||
}
|
||||
|
||||
# === CORE SERVICES ===
|
||||
start_core() {
|
||||
printf "\n---------------------- STARTING CORE -----------------------\n"
|
||||
|
||||
# Due to some instances complaining about this, making sure its there every time.
|
||||
mkdir -p /dev/net
|
||||
mknod /dev/net/tun c 10 200
|
||||
chmod 600 /dev/net/tun
|
||||
|
||||
# Actually starting WGDashboard
|
||||
echo "Activating Python venv and executing the WireGuard Dashboard service."
|
||||
/bin/bash ./wgd.sh start
|
||||
}
|
||||
|
||||
ensure_blocking() {
|
||||
# Wait a second before continuing, to give the python program some time to get ready.
|
||||
sleep 1s
|
||||
echo -e "\nEnsuring container continuation."
|
||||
|
||||
# Find and tail the latest error and access logs if they exist
|
||||
local logdir="${WGDASH}/src/log"
|
||||
|
||||
latestErrLog=$(find "$logdir" -name "error_*.log" -type f -print | sort -r | head -n 1)
|
||||
|
||||
# Only tail the logs if they are found
|
||||
if [ -n "$latestErrLog" ]; then
|
||||
tail -f "$latestErrLog" &
|
||||
|
||||
# Wait for the tail process to end.
|
||||
wait $!
|
||||
else
|
||||
echo "No log files found to tail. Something went wrong, exiting..."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Execute functions for the WireGuard Dashboard services, then set the environment variables
|
||||
ensure_installation
|
||||
set_envvars
|
||||
start_core
|
||||
ensure_blocking
|
BIN
img/Group 2.png
BIN
img/Group 2.png
Binary file not shown.
Before Width: | Height: | Size: 49 KiB |
Binary file not shown.
Before Width: | Height: | Size: 180 KiB |
BIN
img/Group 3.png
BIN
img/Group 3.png
Binary file not shown.
Before Width: | Height: | Size: 61 KiB |
Binary file not shown.
Before Width: | Height: | Size: 221 KiB |
Binary file not shown.
Before Width: | Height: | Size: 54 KiB |
Binary file not shown.
Before Width: | Height: | Size: 198 KiB |
1369
package-lock.json
generated
Normal file
1369
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
7
package.json
Normal file
7
package.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"marked": "^15.0.7",
|
||||
"openai": "^4.89.0",
|
||||
"pinia-plugin-persistedstate": "^4.2.0"
|
||||
}
|
||||
}
|
6
qodana.yaml
Normal file
6
qodana.yaml
Normal file
@ -0,0 +1,6 @@
|
||||
version: "1.0"
|
||||
linter: jetbrains/qodana-python:2024.3
|
||||
profile:
|
||||
name: qodana.recommended
|
||||
include:
|
||||
- name: CheckDependencyLicenses
|
76
src/Utilities.py
Normal file
76
src/Utilities.py
Normal file
@ -0,0 +1,76 @@
|
||||
import re, ipaddress
|
||||
import subprocess
|
||||
|
||||
|
||||
def RegexMatch(regex, text) -> bool:
|
||||
"""
|
||||
Regex Match
|
||||
@param regex: Regex patter
|
||||
@param text: Text to match
|
||||
@return: Boolean indicate if the text match the regex pattern
|
||||
"""
|
||||
pattern = re.compile(regex)
|
||||
return pattern.search(text) is not None
|
||||
|
||||
def GetRemoteEndpoint() -> str:
|
||||
"""
|
||||
Using socket to determine default interface IP address. Thanks, @NOXICS
|
||||
@return:
|
||||
"""
|
||||
import socket
|
||||
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
|
||||
s.connect(("1.1.1.1", 80)) # Connecting to a public IP
|
||||
wgd_remote_endpoint = s.getsockname()[0]
|
||||
return str(wgd_remote_endpoint)
|
||||
|
||||
|
||||
def StringToBoolean(value: str):
|
||||
"""
|
||||
Convert string boolean to boolean
|
||||
@param value: Boolean value in string came from Configuration file
|
||||
@return: Boolean value
|
||||
"""
|
||||
return (value.strip().replace(" ", "").lower() in
|
||||
("yes", "true", "t", "1", 1))
|
||||
|
||||
def ValidateIPAddressesWithRange(ips: str) -> bool:
|
||||
s = ips.replace(" ", "").split(",")
|
||||
for ip in s:
|
||||
try:
|
||||
ipaddress.ip_network(ip)
|
||||
except ValueError as e:
|
||||
return False
|
||||
return True
|
||||
|
||||
def ValidateIPAddresses(ips) -> bool:
|
||||
s = ips.replace(" ", "").split(",")
|
||||
for ip in s:
|
||||
try:
|
||||
ipaddress.ip_address(ip)
|
||||
except ValueError as e:
|
||||
return False
|
||||
return True
|
||||
|
||||
def ValidateDNSAddress(addresses) -> tuple[bool, str]:
|
||||
s = addresses.replace(" ", "").split(",")
|
||||
for address in s:
|
||||
if not ValidateIPAddresses(address) and not RegexMatch(
|
||||
r"(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z][a-z]{0,61}[a-z]", address):
|
||||
return False, f"{address} does not appear to be an valid DNS address"
|
||||
return True, ""
|
||||
|
||||
def GenerateWireguardPublicKey(privateKey: str) -> tuple[bool, str] | tuple[bool, None]:
|
||||
try:
|
||||
publicKey = subprocess.check_output(f"wg pubkey", input=privateKey.encode(), shell=True,
|
||||
stderr=subprocess.STDOUT)
|
||||
return True, publicKey.decode().strip('\n')
|
||||
except subprocess.CalledProcessError:
|
||||
return False, None
|
||||
|
||||
def GenerateWireguardPrivateKey() -> tuple[bool, str] | tuple[bool, None]:
|
||||
try:
|
||||
publicKey = subprocess.check_output(f"wg genkey", shell=True,
|
||||
stderr=subprocess.STDOUT)
|
||||
return True, publicKey.decode().strip('\n')
|
||||
except subprocess.CalledProcessError:
|
||||
return False, None
|
4
src/certbot.ini
Normal file
4
src/certbot.ini
Normal file
@ -0,0 +1,4 @@
|
||||
authenticator = standalone
|
||||
noninteractive = true
|
||||
agree-tos = true
|
||||
rsa-key-size = 2048
|
3743
src/dashboard.py
3743
src/dashboard.py
File diff suppressed because it is too large
Load Diff
@ -1 +0,0 @@
|
||||
You can delete this later ;)
|
@ -1,34 +0,0 @@
|
||||
[Interface]
|
||||
Address = 10.200.200.1/24
|
||||
SaveConfig = true
|
||||
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
|
||||
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
|
||||
ListenPort = 51820
|
||||
PrivateKey = 8DsSMli3okgUx5frKbFQ0fMW5ZMyqyxOdOW7+g21L18=
|
||||
|
||||
|
||||
[Peer]
|
||||
#Name = 10
|
||||
PublicKey = Hw2sISygeuT4eQyubDdP0CA2RJHYcpHhBOnIn6riEA0=
|
||||
AllowedIPs = 10.200.200.9/32, 10.200.200.2/32
|
||||
Endpoint = 142.114.220.189:58403
|
||||
|
||||
[Peer]
|
||||
PublicKey = 0pCjuGUyXIxTmCZCoFeVtMOgZFVkU9WPGilJxLpYVAI=
|
||||
AllowedIPs = 10.200.200.3/32
|
||||
Endpoint = 76.67.102.20:55349
|
||||
|
||||
[Peer]
|
||||
PublicKey = sJrgj14BfToasB5EhQfUjw2xTj3FoU/lSca9bDx+2Ww=
|
||||
AllowedIPs = 10.200.200.4/32
|
||||
Endpoint = 175.0.140.3:59637
|
||||
|
||||
[Peer]
|
||||
PublicKey = IxM4gsOWugRtQ0WmFnaAYUCVquTsSqxHiE7oqisKsRQ=
|
||||
AllowedIPs = 10.200.200.5/32
|
||||
Endpoint = 180.152.230.148:61618
|
||||
|
||||
[Peer]
|
||||
PublicKey = TSsTB1NPTOHfqNkcNZbJQiz+XcJ32AudypDwa5ItmBM=
|
||||
AllowedIPs = 10.200.200.6/32
|
||||
Endpoint = 118.250.38.191:51820
|
26
src/gunicorn.conf.py
Normal file
26
src/gunicorn.conf.py
Normal file
@ -0,0 +1,26 @@
|
||||
import os.path
|
||||
import dashboard, configparser
|
||||
from datetime import datetime
|
||||
global sqldb, cursor, DashboardConfig, WireguardConfigurations, AllPeerJobs, JobLogger
|
||||
app_host, app_port = dashboard.gunicornConfig()
|
||||
date = datetime.today().strftime('%Y_%m_%d_%H_%M_%S')
|
||||
|
||||
def post_worker_init(worker):
|
||||
dashboard.startThreads()
|
||||
|
||||
worker_class = 'gthread'
|
||||
workers = 1
|
||||
threads = 1
|
||||
bind = f"{app_host}:{app_port}"
|
||||
daemon = True
|
||||
pidfile = './gunicorn.pid'
|
||||
wsgi_app = "dashboard:app"
|
||||
accesslog = f"./log/access_{date}.log"
|
||||
log_level = "debug"
|
||||
capture_output = True
|
||||
errorlog = f"./log/error_{date}.log"
|
||||
pythonpath = "., ./modules"
|
||||
|
||||
print(f"[Gunicorn] WGDashboard w/ Gunicorn will be running on {bind}", flush=True)
|
||||
print(f"[Gunicorn] Access log file is at {accesslog}", flush=True)
|
||||
print(f"[Gunicorn] Error log file is at {errorlog}", flush=True)
|
35
src/modules/DashboardLogger.py
Normal file
35
src/modules/DashboardLogger.py
Normal file
@ -0,0 +1,35 @@
|
||||
"""
|
||||
Dashboard Logger Class
|
||||
"""
|
||||
import sqlite3, os, uuid
|
||||
|
||||
class DashboardLogger:
|
||||
def __init__(self, CONFIGURATION_PATH):
|
||||
self.loggerdb = sqlite3.connect(os.path.join(CONFIGURATION_PATH, 'db', 'wgdashboard_log.db'),
|
||||
isolation_level=None,
|
||||
check_same_thread=False)
|
||||
self.loggerdb.row_factory = sqlite3.Row
|
||||
self.__createLogDatabase()
|
||||
self.log(Message="WGDashboard started")
|
||||
def __createLogDatabase(self):
|
||||
with self.loggerdb:
|
||||
loggerdbCursor = self.loggerdb.cursor()
|
||||
existingTable = loggerdbCursor.execute("SELECT name from sqlite_master where type='table'").fetchall()
|
||||
existingTable = [t['name'] for t in existingTable]
|
||||
if "DashboardLog" not in existingTable:
|
||||
loggerdbCursor.execute(
|
||||
"CREATE TABLE DashboardLog (LogID VARCHAR NOT NULL, LogDate DATETIME DEFAULT (strftime('%Y-%m-%d %H:%M:%S','now', 'localtime')), URL VARCHAR, IP VARCHAR, Status VARCHAR, Message VARCHAR, PRIMARY KEY (LogID))")
|
||||
if self.loggerdb.in_transaction:
|
||||
self.loggerdb.commit()
|
||||
|
||||
def log(self, URL: str = "", IP: str = "", Status: str = "true", Message: str = "") -> bool:
|
||||
try:
|
||||
loggerdbCursor = self.loggerdb.cursor()
|
||||
loggerdbCursor.execute(
|
||||
"INSERT INTO DashboardLog (LogID, URL, IP, Status, Message) VALUES (?, ?, ?, ?, ?);", (str(uuid.uuid4()), URL, IP, Status, Message,))
|
||||
loggerdbCursor.close()
|
||||
self.loggerdb.commit()
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"[WGDashboard] Access Log Error: {str(e)}")
|
||||
return False
|
69
src/modules/Email.py
Normal file
69
src/modules/Email.py
Normal file
@ -0,0 +1,69 @@
|
||||
import os.path
|
||||
import smtplib
|
||||
from email import encoders
|
||||
from email.header import Header
|
||||
from email.mime.base import MIMEBase
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.text import MIMEText
|
||||
from email.utils import formataddr
|
||||
|
||||
class EmailSender:
|
||||
def __init__(self, DashboardConfig):
|
||||
self.smtp = None
|
||||
self.DashboardConfig = DashboardConfig
|
||||
if not os.path.exists('./attachments'):
|
||||
os.mkdir('./attachments')
|
||||
|
||||
def Server(self):
|
||||
return self.DashboardConfig.GetConfig("Email", "server")[1]
|
||||
|
||||
def Port(self):
|
||||
return self.DashboardConfig.GetConfig("Email", "port")[1]
|
||||
|
||||
def Encryption(self):
|
||||
return self.DashboardConfig.GetConfig("Email", "encryption")[1]
|
||||
|
||||
def Username(self):
|
||||
return self.DashboardConfig.GetConfig("Email", "username")[1]
|
||||
|
||||
def Password(self):
|
||||
return self.DashboardConfig.GetConfig("Email", "email_password")[1]
|
||||
|
||||
def SendFrom(self):
|
||||
return self.DashboardConfig.GetConfig("Email", "send_from")[1]
|
||||
|
||||
def ready(self):
|
||||
return len(self.Server()) > 0 and len(self.Port()) > 0 and len(self.Encryption()) > 0 and len(self.Username()) > 0 and len(self.Password()) > 0 and len(self.SendFrom())
|
||||
|
||||
def send(self, receiver, subject, body, includeAttachment = False, attachmentName = ""):
|
||||
if self.ready():
|
||||
try:
|
||||
self.smtp = smtplib.SMTP(self.Server(), port=int(self.Port()))
|
||||
self.smtp.ehlo()
|
||||
if self.Encryption() == "STARTTLS":
|
||||
self.smtp.starttls()
|
||||
self.smtp.login(self.Username(), self.Password())
|
||||
message = MIMEMultipart()
|
||||
message['Subject'] = subject
|
||||
message['From'] = self.SendFrom()
|
||||
message["To"] = receiver
|
||||
message.attach(MIMEText(body, "plain"))
|
||||
|
||||
if includeAttachment and len(attachmentName) > 0:
|
||||
attachmentPath = os.path.join('./attachments', attachmentName)
|
||||
if os.path.exists(attachmentPath):
|
||||
attachment = MIMEBase("application", "octet-stream")
|
||||
with open(os.path.join('./attachments', attachmentName), 'rb') as f:
|
||||
attachment.set_payload(f.read())
|
||||
encoders.encode_base64(attachment)
|
||||
attachment.add_header("Content-Disposition", f"attachment; filename= {attachmentName}",)
|
||||
message.attach(attachment)
|
||||
else:
|
||||
self.smtp.close()
|
||||
return False, "Attachment does not exist"
|
||||
self.smtp.sendmail(self.SendFrom(), receiver, message.as_string())
|
||||
self.smtp.close()
|
||||
return True, None
|
||||
except Exception as e:
|
||||
return False, f"Send failed | Reason: {e}"
|
||||
return False, "SMTP not configured"
|
22
src/modules/Log.py
Normal file
22
src/modules/Log.py
Normal file
@ -0,0 +1,22 @@
|
||||
"""
|
||||
Log Class
|
||||
"""
|
||||
class Log:
|
||||
def __init__(self, LogID: str, JobID: str, LogDate: str, Status: str, Message: str):
|
||||
self.LogID = LogID
|
||||
self.JobID = JobID
|
||||
self.LogDate = LogDate
|
||||
self.Status = Status
|
||||
self.Message = Message
|
||||
|
||||
def toJson(self):
|
||||
return {
|
||||
"LogID": self.LogID,
|
||||
"JobID": self.JobID,
|
||||
"LogDate": self.LogDate,
|
||||
"Status": self.Status,
|
||||
"Message": self.Message
|
||||
}
|
||||
|
||||
def __dict__(self):
|
||||
return self.toJson()
|
32
src/modules/PeerJob.py
Normal file
32
src/modules/PeerJob.py
Normal file
@ -0,0 +1,32 @@
|
||||
"""
|
||||
Peer Job
|
||||
"""
|
||||
from datetime import datetime
|
||||
class PeerJob:
|
||||
def __init__(self, JobID: str, Configuration: str, Peer: str,
|
||||
Field: str, Operator: str, Value: str, CreationDate: datetime, ExpireDate: datetime, Action: str):
|
||||
self.Action = Action
|
||||
self.ExpireDate = ExpireDate
|
||||
self.CreationDate = CreationDate
|
||||
self.Value = Value
|
||||
self.Operator = Operator
|
||||
self.Field = Field
|
||||
self.Configuration = Configuration
|
||||
self.Peer = Peer
|
||||
self.JobID = JobID
|
||||
|
||||
def toJson(self):
|
||||
return {
|
||||
"JobID": self.JobID,
|
||||
"Configuration": self.Configuration,
|
||||
"Peer": self.Peer,
|
||||
"Field": self.Field,
|
||||
"Operator": self.Operator,
|
||||
"Value": self.Value,
|
||||
"CreationDate": self.CreationDate,
|
||||
"ExpireDate": self.ExpireDate,
|
||||
"Action": self.Action
|
||||
}
|
||||
|
||||
def __dict__(self):
|
||||
return self.toJson()
|
53
src/modules/PeerJobLogger.py
Normal file
53
src/modules/PeerJobLogger.py
Normal file
@ -0,0 +1,53 @@
|
||||
"""
|
||||
Peer Job Logger
|
||||
"""
|
||||
import sqlite3, os, uuid
|
||||
from .Log import Log
|
||||
|
||||
class PeerJobLogger:
|
||||
def __init__(self, CONFIGURATION_PATH, AllPeerJobs):
|
||||
self.loggerdb = sqlite3.connect(os.path.join(CONFIGURATION_PATH, 'db', 'wgdashboard_log.db'),
|
||||
check_same_thread=False)
|
||||
self.loggerdb.row_factory = sqlite3.Row
|
||||
self.logs: list[Log] = []
|
||||
self.__createLogDatabase()
|
||||
self.AllPeerJobs = AllPeerJobs
|
||||
def __createLogDatabase(self):
|
||||
with self.loggerdb:
|
||||
loggerdbCursor = self.loggerdb.cursor()
|
||||
|
||||
existingTable = loggerdbCursor.execute("SELECT name from sqlite_master where type='table'").fetchall()
|
||||
existingTable = [t['name'] for t in existingTable]
|
||||
|
||||
if "JobLog" not in existingTable:
|
||||
loggerdbCursor.execute("CREATE TABLE JobLog (LogID VARCHAR NOT NULL, JobID NOT NULL, LogDate DATETIME DEFAULT (strftime('%Y-%m-%d %H:%M:%S','now', 'localtime')), Status VARCHAR NOT NULL, Message VARCHAR, PRIMARY KEY (LogID))")
|
||||
if self.loggerdb.in_transaction:
|
||||
self.loggerdb.commit()
|
||||
def log(self, JobID: str, Status: bool = True, Message: str = "") -> bool:
|
||||
try:
|
||||
with self.loggerdb:
|
||||
loggerdbCursor = self.loggerdb.cursor()
|
||||
loggerdbCursor.execute(f"INSERT INTO JobLog (LogID, JobID, Status, Message) VALUES (?, ?, ?, ?)",
|
||||
(str(uuid.uuid4()), JobID, Status, Message,))
|
||||
if self.loggerdb.in_transaction:
|
||||
self.loggerdb.commit()
|
||||
except Exception as e:
|
||||
print(f"[WGDashboard] Peer Job Log Error: {str(e)}")
|
||||
return False
|
||||
return True
|
||||
|
||||
def getLogs(self, all: bool = False, configName = None) -> list[Log]:
|
||||
logs: list[Log] = []
|
||||
try:
|
||||
allJobs = self.AllPeerJobs.getAllJobs(configName)
|
||||
allJobsID = ", ".join([f"'{x.JobID}'" for x in allJobs])
|
||||
with self.loggerdb:
|
||||
loggerdbCursor = self.loggerdb.cursor()
|
||||
table = loggerdbCursor.execute(f"SELECT * FROM JobLog WHERE JobID IN ({allJobsID}) ORDER BY LogDate DESC").fetchall()
|
||||
self.logs.clear()
|
||||
for l in table:
|
||||
logs.append(
|
||||
Log(l["LogID"], l["JobID"], l["LogDate"], l["Status"], l["Message"]))
|
||||
except Exception as e:
|
||||
return logs
|
||||
return logs
|
135
src/modules/SystemStatus.py
Normal file
135
src/modules/SystemStatus.py
Normal file
@ -0,0 +1,135 @@
|
||||
import psutil
|
||||
class SystemStatus:
|
||||
def __init__(self):
|
||||
self.CPU = CPU()
|
||||
self.MemoryVirtual = Memory('virtual')
|
||||
self.MemorySwap = Memory('swap')
|
||||
self.Disks = Disks()
|
||||
self.NetworkInterfaces = NetworkInterfaces()
|
||||
self.Processes = Processes()
|
||||
def toJson(self):
|
||||
return {
|
||||
"CPU": self.CPU,
|
||||
"Memory": {
|
||||
"VirtualMemory": self.MemoryVirtual,
|
||||
"SwapMemory": self.MemorySwap
|
||||
},
|
||||
"Disks": self.Disks,
|
||||
"NetworkInterfaces": self.NetworkInterfaces,
|
||||
"Processes": self.Processes
|
||||
}
|
||||
|
||||
|
||||
class CPU:
|
||||
def __init__(self):
|
||||
self.cpu_percent: float = 0
|
||||
self.cpu_percent_per_cpu: list[float] = []
|
||||
def getData(self):
|
||||
try:
|
||||
self.cpu_percent_per_cpu = psutil.cpu_percent(interval=0.5, percpu=True)
|
||||
self.cpu_percent = psutil.cpu_percent(interval=0.5)
|
||||
except Exception as e:
|
||||
pass
|
||||
def toJson(self):
|
||||
self.getData()
|
||||
return self.__dict__
|
||||
|
||||
class Memory:
|
||||
def __init__(self, memoryType: str):
|
||||
self.__memoryType__ = memoryType
|
||||
self.total = 0
|
||||
self.available = 0
|
||||
self.percent = 0
|
||||
def getData(self):
|
||||
try:
|
||||
if self.__memoryType__ == "virtual":
|
||||
memory = psutil.virtual_memory()
|
||||
else:
|
||||
memory = psutil.swap_memory()
|
||||
self.total = memory.total
|
||||
self.available = memory.available
|
||||
self.percent = memory.percent
|
||||
except Exception as e:
|
||||
pass
|
||||
def toJson(self):
|
||||
self.getData()
|
||||
return self.__dict__
|
||||
|
||||
class Disks:
|
||||
def __init__(self):
|
||||
self.disks : list[Disk] = []
|
||||
def getData(self):
|
||||
try:
|
||||
self.disks = list(map(lambda x : Disk(x.mountpoint), psutil.disk_partitions()))
|
||||
except Exception as e:
|
||||
pass
|
||||
def toJson(self):
|
||||
self.getData()
|
||||
return self.disks
|
||||
|
||||
class Disk:
|
||||
def __init__(self, mountPoint: str):
|
||||
self.total = 0
|
||||
self.used = 0
|
||||
self.free = 0
|
||||
self.percent = 0
|
||||
self.mountPoint = mountPoint
|
||||
def getData(self):
|
||||
try:
|
||||
disk = psutil.disk_usage(self.mountPoint)
|
||||
self.total = disk.total
|
||||
self.free = disk.free
|
||||
self.used = disk.used
|
||||
self.percent = disk.percent
|
||||
except Exception as e:
|
||||
pass
|
||||
def toJson(self):
|
||||
self.getData()
|
||||
return self.__dict__
|
||||
|
||||
class NetworkInterfaces:
|
||||
def __init__(self):
|
||||
self.interfaces = {}
|
||||
def getData(self):
|
||||
try:
|
||||
network = psutil.net_io_counters(pernic=True, nowrap=True)
|
||||
for i in network.keys():
|
||||
self.interfaces[i] = network[i]._asdict()
|
||||
except Exception as e:
|
||||
pass
|
||||
def toJson(self):
|
||||
self.getData()
|
||||
return self.interfaces
|
||||
|
||||
class Process:
|
||||
def __init__(self, name, command, pid, percent):
|
||||
self.name = name
|
||||
self.command = command
|
||||
self.pid = pid
|
||||
self.percent = percent
|
||||
def toJson(self):
|
||||
return self.__dict__
|
||||
|
||||
class Processes:
|
||||
def __init__(self):
|
||||
self.CPU_Top_10_Processes: list[Process] = []
|
||||
self.Memory_Top_10_Processes: list[Process] = []
|
||||
def getData(self):
|
||||
while True:
|
||||
try:
|
||||
processes = list(psutil.process_iter())
|
||||
self.CPU_Top_10_Processes = sorted(
|
||||
list(map(lambda x : Process(x.name(), " ".join(x.cmdline()), x.pid, x.cpu_percent()), processes)),
|
||||
key=lambda x : x.percent, reverse=True)[:20]
|
||||
self.Memory_Top_10_Processes = sorted(
|
||||
list(map(lambda x : Process(x.name(), " ".join(x.cmdline()), x.pid, x.memory_percent()), processes)),
|
||||
key=lambda x : x.percent, reverse=True)[:20]
|
||||
break
|
||||
except Exception as e:
|
||||
break
|
||||
def toJson(self):
|
||||
self.getData()
|
||||
return {
|
||||
"cpu_top_10": self.CPU_Top_10_Processes,
|
||||
"memory_top_10": self.Memory_Top_10_Processes
|
||||
}
|
@ -1,4 +1,10 @@
|
||||
Flask==1.1.2
|
||||
tinydb==4.3.0
|
||||
ifcfg==0.21
|
||||
icmplib==2.1.1
|
||||
bcrypt
|
||||
ifcfg
|
||||
psutil
|
||||
pyotp
|
||||
Flask
|
||||
flask-cors
|
||||
icmplib
|
||||
gunicorn
|
||||
requests
|
||||
tcconfig
|
BIN
src/static/.DS_Store
vendored
BIN
src/static/.DS_Store
vendored
Binary file not shown.
30
src/static/app/.gitignore
vendored
Normal file
30
src/static/app/.gitignore
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist-ssr
|
||||
coverage
|
||||
*.local
|
||||
|
||||
/cypress/videos/
|
||||
/cypress/screenshots/
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
*.tsbuildinfo
|
||||
.vite/*
|
27
src/static/app/build.sh
Executable file
27
src/static/app/build.sh
Executable file
@ -0,0 +1,27 @@
|
||||
#!/bin/bash
|
||||
echo "Running vite build..."
|
||||
if vite build; then
|
||||
echo "Vite build successful."
|
||||
else
|
||||
echo "Vite build failed. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
echo "Checking for changes to commit..."
|
||||
if git diff-index --quiet HEAD --; then
|
||||
|
||||
if git commit -a; then
|
||||
echo "Git commit successful."
|
||||
else
|
||||
echo "Git commit failed. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "No changes to commit. Skipping commit."
|
||||
fi
|
||||
echo "Pushing changes to remote..."
|
||||
if git push; then
|
||||
echo "Git push successful."
|
||||
else
|
||||
echo "Git push failed. Exiting."
|
||||
exit 1
|
||||
fi
|
BIN
src/static/app/dist/assets/bootstrap-icons-BOrJxbIo.woff
vendored
Normal file
BIN
src/static/app/dist/assets/bootstrap-icons-BOrJxbIo.woff
vendored
Normal file
Binary file not shown.
BIN
src/static/app/dist/assets/bootstrap-icons-BtvjY1KL.woff2
vendored
Normal file
BIN
src/static/app/dist/assets/bootstrap-icons-BtvjY1KL.woff2
vendored
Normal file
Binary file not shown.
8
src/static/app/dist/assets/browser-CjSdxGTc.js
vendored
Normal file
8
src/static/app/dist/assets/browser-CjSdxGTc.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/static/app/dist/assets/configuration-qGYhSc1H.js
vendored
Normal file
1
src/static/app/dist/assets/configuration-qGYhSc1H.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
import{_ as r,c as i,d as o,w as e,k as l,a as t,j as _,i as a,l as d,S as u}from"./index-DZliHkQD.js";const m={name:"configuration"},p={class:"mt-md-5 mt-3 text-body"};function f(k,x,h,w,$,v){const n=l("RouterView");return t(),i("div",p,[o(n,null,{default:e(({Component:s,route:c})=>[o(_,{name:"fade2",mode:"out-in"},{default:e(()=>[(t(),a(u,null,{default:e(()=>[(t(),a(d(s),{key:c.path}))]),_:2},1024))]),_:2},1024)]),_:1})])}const B=r(m,[["render",f]]);export{B as default};
|
1
src/static/app/dist/assets/configurationList-BY8izVeQ.css
vendored
Normal file
1
src/static/app/dist/assets/configurationList-BY8izVeQ.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
.fade-enter-active[data-v-dafd6275]{transition-delay:var(--7d032b58)!important}.progress-bar[data-v-c20f1a80]{width:0;transition:all 1s cubic-bezier(.42,0,.22,1)}.filter a[data-v-ea61b607]{text-decoration:none}
|
1
src/static/app/dist/assets/configurationList-Cznk60kB.js
vendored
Normal file
1
src/static/app/dist/assets/configurationList-Cznk60kB.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/static/app/dist/assets/dayjs.min-PaIL06iQ.js
vendored
Normal file
1
src/static/app/dist/assets/dayjs.min-PaIL06iQ.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/static/app/dist/assets/editConfiguration-Ca_IlmFH.css
vendored
Normal file
1
src/static/app/dist/assets/editConfiguration-Ca_IlmFH.css
vendored
Normal file
File diff suppressed because one or more lines are too long
7
src/static/app/dist/assets/editConfiguration-gjtFMIrx.js
vendored
Normal file
7
src/static/app/dist/assets/editConfiguration-gjtFMIrx.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/static/app/dist/assets/index-2ZxMyhlP.css
vendored
Normal file
1
src/static/app/dist/assets/index-2ZxMyhlP.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
.agentMessage[data-v-8635cf47]{white-space:break-spaces;max-width:80%;display:flex;flex-direction:column;word-wrap:break-word}.text-bg-secondary[data-v-8635cf47]{background-color:RGBA(var(--bs-secondary-rgb),.7)!important}.text-bg-primary[data-v-8635cf47]{background-color:RGBA(var(--bs-primary-rgb),.7)!important}.agentContainer[data-v-a76f42bd]{--agentHeight: 100vh;position:absolute;z-index:9999;top:0;left:100%;width:450px;box-shadow:0 10px 30px #0000004d;backdrop-filter:blur(8px);background:linear-gradient(var(--degree),#009dff52 var(--distance2),#F9464752 100%)}.agentContainer.enabled[data-v-a76f42bd]{height:calc(var(--agentHeight) - 1rem)}@media screen and (max-width: 768px){.agentContainer[data-v-a76f42bd]{--agentHeight: 100vh !important;top:0;left:0;max-height:calc(var(--agentHeight) - 58px - 1rem);width:calc(100% - 1rem)}}.agentChatroomBody[data-v-a76f42bd]{flex:1 1 auto;overflow-y:auto;max-height:calc(var(--agentHeight) - 70px - 244px)}@media screen and (max-width: 768px){.navbar-container[data-v-58e71749]{position:absolute!important;z-index:1000;animation-duration:.4s;animation-fill-mode:both;display:none;animation-timing-function:cubic-bezier(.82,.58,.17,.9)}.navbar-container.active[data-v-58e71749]{animation-direction:normal;display:block!important;animation-name:zoomInFade-58e71749}}.navbar-container[data-v-58e71749]{height:100vh;position:relative}@supports (height: 100dvh){@media screen and (max-width: 768px){.navbar-container[data-v-58e71749]{height:calc(100dvh - 58px)}}}@keyframes zoomInFade-58e71749{0%{opacity:0;transform:translateY(60px);filter:blur(3px)}to{opacity:1;transform:translateY(0);filter:blur(0px)}}.slideIn-enter-active[data-v-58e71749],.slideIn-leave-active[data-v-58e71749]{transition:all .3s cubic-bezier(.82,.58,.17,1)}.slideIn-enter-from[data-v-58e71749],.slideIn-leave-to[data-v-58e71749]{transform:translateY(30px);filter:blur(3px);opacity:0}main[data-v-0c6a5068]{height:100vh}@supports (height: 100dvh){@media screen and (max-width: 768px){main[data-v-0c6a5068]{height:calc(100dvh - 58px)}}}
|
15
src/static/app/dist/assets/index-DFl-XeJT.css
vendored
Normal file
15
src/static/app/dist/assets/index-DFl-XeJT.css
vendored
Normal file
File diff suppressed because one or more lines are too long
44
src/static/app/dist/assets/index-DZliHkQD.js
vendored
Normal file
44
src/static/app/dist/assets/index-DZliHkQD.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/static/app/dist/assets/index-L60y6kc9.js
vendored
Normal file
1
src/static/app/dist/assets/index-L60y6kc9.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
function f(e){return e.includes(":")?6:e.includes(".")?4:0}function b(e){const i=f(e);if(!i)throw new Error(`Invalid IP address: ${e}`);let n=0n,o=0n;const r=Object.create(null);if(i===4)for(const s of e.split(".").map(BigInt).reverse())n+=s*2n**o,o+=8n;else{if(e.includes(".")&&(r.ipv4mapped=!0,e=e.split(":").map(t=>{if(t.includes(".")){const[c,l,d,a]=t.split(".").map($=>Number($).toString(16).padStart(2,"0"));return`${c}${l}:${d}${a}`}else return t}).join(":")),e.includes("%")){let t;[,e,t]=/(.+)%(.+)/.exec(e)||[],r.scopeid=t}const s=e.split(":"),u=s.indexOf("");if(u!==-1)for(;s.length<8;)s.splice(u,0,"");for(const t of s.map(c=>BigInt(parseInt(c||"0",16))).reverse())n+=t*2n**o,o+=16n}return r.number=n,r.version=i,r}const p={4:32,6:128},I=e=>e.includes("/")?f(e):0;function m(e){const i=I(e),n=Object.create(null);if(i)n.cidr=e,n.version=i;else{const a=f(e);if(a)n.cidr=`${e}/${p[a]}`,n.version=a;else throw new Error(`Network is not a CIDR or IP: ${e}`)}const[o,r]=n.cidr.split("/");if(!/^[0-9]+$/.test(r))throw new Error(`Network is not a CIDR or IP: ${e}`);n.prefix=r,n.single=r===String(p[n.version]);const{number:s,version:u}=b(o),t=p[u],c=s.toString(2).padStart(t,"0"),l=Number(t-r),d=c.substring(0,t-l);return n.start=BigInt(`0b${d}${"0".repeat(l)}`),n.end=BigInt(`0b${d}${"1".repeat(l)}`),n}export{m as p};
|
56
src/static/app/dist/assets/index-UG7VB4Xm.js
vendored
Normal file
56
src/static/app/dist/assets/index-UG7VB4Xm.js
vendored
Normal file
File diff suppressed because one or more lines are too long
18
src/static/app/dist/assets/index-myupzXki.js
vendored
Normal file
18
src/static/app/dist/assets/index-myupzXki.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/static/app/dist/assets/localeText-DG9SnJT8.js
vendored
Normal file
1
src/static/app/dist/assets/localeText-DG9SnJT8.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
import{_ as e,G as t,a as o,c as a,t as c}from"./index-DZliHkQD.js";const s={name:"localeText",props:{t:""},computed:{getLocaleText(){return t(this.t)}}};function n(r,p,l,_,i,x){return o(),a("span",null,c(this.getLocaleText),1)}const u=e(s,[["render",n]]);export{u as L};
|
1
src/static/app/dist/assets/message-BaDb-qC9.css
vendored
Normal file
1
src/static/app/dist/assets/message-BaDb-qC9.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
.message[data-v-94c76b54]{width:100%}@media screen and (min-width: 576px){.message[data-v-94c76b54]{width:400px}}
|
1
src/static/app/dist/assets/message-DZx7QSKr.js
vendored
Normal file
1
src/static/app/dist/assets/message-DZx7QSKr.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
import{L as l}from"./localeText-DG9SnJT8.js";import{d as c}from"./dayjs.min-PaIL06iQ.js";import{_ as h,a as o,c as a,b as e,d as i,w as u,f as p,t as n,j as g,n as f,k as _}from"./index-DZliHkQD.js";const x={name:"message",methods:{dayjs:c,hide(){this.ct(),this.message.show=!1},show(){this.timeout=setTimeout(()=>{this.message.show=!1},5e3)},ct(){clearTimeout(this.timeout)}},components:{LocaleText:l},props:{message:Object},mounted(){this.show()},data(){return{dismiss:!1,timeout:null}}},v=["id"],b={key:0,class:"d-flex"},w={class:"fw-bold d-block",style:{"text-transform":"uppercase"}},y={class:"ms-auto"},k={key:1},T={class:"card-body d-flex align-items-center gap-3"};function M(j,s,C,L,t,m){const d=_("LocaleText");return o(),a("div",{onMouseenter:s[1]||(s[1]=r=>{t.dismiss=!0,this.ct()}),onMouseleave:s[2]||(s[2]=r=>{t.dismiss=!1,this.show()}),class:"card shadow rounded-3 position-relative message ms-auto",id:this.message.id},[e("div",{class:f([{"text-bg-danger":this.message.type==="danger","text-bg-success":this.message.type==="success","text-bg-warning":this.message.type==="warning"},"card-header pos"])},[i(g,{name:"zoom",mode:"out-in"},{default:u(()=>[t.dismiss?(o(),a("div",k,[e("small",{onClick:s[0]||(s[0]=r=>m.hide()),class:"d-block mx-auto w-100 text-center",style:{cursor:"pointer"}},[s[3]||(s[3]=e("i",{class:"bi bi-x-lg me-2"},null,-1)),i(d,{t:"Dismiss"})])])):(o(),a("div",b,[e("small",w,[i(d,{t:"FROM "}),p(" "+n(this.message.from),1)]),e("small",y,n(m.dayjs().format("hh:mm A")),1)]))]),_:1})],2),e("div",T,[e("div",null,n(this.message.content),1)])],40,v)}const z=h(x,[["render",M],["__scopeId","data-v-94c76b54"]]);export{z as M};
|
1
src/static/app/dist/assets/newConfiguration-CAFzjDsW.css
vendored
Normal file
1
src/static/app/dist/assets/newConfiguration-CAFzjDsW.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
.protocolBtnGroup a[data-v-b97242f3]{transition:all .2s ease-in-out}
|
3
src/static/app/dist/assets/newConfiguration-CPAMxqV6.js
vendored
Normal file
3
src/static/app/dist/assets/newConfiguration-CPAMxqV6.js
vendored
Normal file
File diff suppressed because one or more lines are too long
10
src/static/app/dist/assets/osmap-CmjRjQ0N.js
vendored
Normal file
10
src/static/app/dist/assets/osmap-CmjRjQ0N.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/static/app/dist/assets/osmap-CoctJCk_.css
vendored
Normal file
1
src/static/app/dist/assets/osmap-CoctJCk_.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/static/app/dist/assets/peerAddModal-DD-hu-9U.js
vendored
Normal file
1
src/static/app/dist/assets/peerAddModal-DD-hu-9U.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/static/app/dist/assets/peerAddModal-s_w1PY7H.css
vendored
Normal file
1
src/static/app/dist/assets/peerAddModal-s_w1PY7H.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
.list-move[data-v-ed72944d],.list-enter-active[data-v-ed72944d],.list-leave-active[data-v-ed72944d]{transition:all .3s ease}.list-enter-from[data-v-ed72944d],.list-leave-to[data-v-ed72944d]{opacity:0;transform:translateY(10px)}.list-leave-active[data-v-ed72944d]{position:absolute}
|
1
src/static/app/dist/assets/peerConfigurationFile-BFmmapnE.css
vendored
Normal file
1
src/static/app/dist/assets/peerConfigurationFile-BFmmapnE.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
.slide-up-enter-active[data-v-b0ea2d46],.slide-up-leave-active[data-v-b0ea2d46]{transition:all .2s cubic-bezier(.42,0,.22,1)}.slide-up-enter-from[data-v-b0ea2d46],.slide-up-leave-to[data-v-b0ea2d46]{opacity:0;transform:scale(.9)}@keyframes spin-b0ea2d46{0%{transform:rotate(0)}to{transform:rotate(360deg)}}#check[data-v-b0ea2d46]{animation:cubic-bezier(.42,0,.22,1.3) .7s spin-b0ea2d46}
|
1
src/static/app/dist/assets/peerConfigurationFile-BaTwLYIc.js
vendored
Normal file
1
src/static/app/dist/assets/peerConfigurationFile-BaTwLYIc.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
import{_ as v,D as g,r as o,o as h,J as x,g as y,a as i,c as n,b as s,d as c,n as w,e as C,w as k,j as F}from"./index-DZliHkQD.js";import{L as T}from"./localeText-DG9SnJT8.js";import"./browser-CjSdxGTc.js";const M={class:"peerSettingContainer w-100 h-100 position-absolute top-0 start-0"},S={class:"container d-flex h-100 w-100"},D={class:"m-auto modal-dialog-centered dashboardModal justify-content-center"},P={class:"card rounded-3 shadow w-100"},j={class:"card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-0"},B={class:"mb-0"},G={class:"card-body p-4 d-flex flex-column gap-3"},L={style:{height:"300px"},class:"d-flex"},N=["value"],V={key:0,class:"spinner-border m-auto",role:"status"},I={class:"d-flex"},W=["disabled"],$={key:0,class:"d-block"},q={key:1,class:"d-block",id:"check"},z={__name:"peerConfigurationFile",props:{selectedPeer:Object},emits:["close"],setup(u,{emit:p}){const m=p,f=u,r=g(),t=o(!1),l=o(""),a=o(!0);o({error:!1,message:void 0}),h(()=>{const d=x();y("/api/downloadPeer/"+d.params.id,{id:f.selectedPeer.id},e=>{e.status?(l.value=e.data.file,a.value=!1):this.dashboardStore.newMessage("Server",e.message,"danger")})});const b=async()=>{navigator.clipboard&&navigator.clipboard.writeText?navigator.clipboard.writeText(l.value).then(()=>{t.value=!0,setTimeout(()=>{t.value=!1},3e3)}).catch(()=>{r.newMessage("WGDashboard","Failed to copy","danger")}):(document.querySelector("#peerConfigurationFile").select(),document.execCommand("copy")?(t.value=!0,setTimeout(()=>{t.value=!1},3e3)):r.newMessage("WGDashboard","Failed to copy","danger"))};return(d,e)=>(i(),n("div",M,[s("div",S,[s("div",D,[s("div",P,[s("div",j,[s("h4",B,[c(T,{t:"Peer Configuration File"})]),s("button",{type:"button",class:"btn-close ms-auto",onClick:e[0]||(e[0]=_=>m("close"))})]),s("div",G,[s("div",L,[s("textarea",{style:{height:"300px"},class:w(["form-control w-100 rounded-3 animate__fadeIn animate__faster animate__animated",{"d-none":a.value}]),id:"peerConfigurationFile",value:l.value},null,10,N),a.value?(i(),n("div",V,e[2]||(e[2]=[s("span",{class:"visually-hidden"},"Loading...",-1)]))):C("",!0)]),s("div",I,[s("button",{onClick:e[1]||(e[1]=_=>b()),disabled:t.value||a.value,class:"ms-auto btn bg-primary-subtle border-primary-subtle text-primary-emphasis rounded-3 position-relative"},[c(F,{name:"slide-up",mode:"out-in"},{default:k(()=>[t.value?(i(),n("span",q,e[4]||(e[4]=[s("i",{class:"bi bi-check-circle-fill"},null,-1)]))):(i(),n("span",$,e[3]||(e[3]=[s("i",{class:"bi bi-clipboard-fill"},null,-1)])))]),_:1})],8,W)])])])])])]))}},R=v(z,[["__scopeId","data-v-b0ea2d46"]]);export{R as default};
|
1
src/static/app/dist/assets/peerJobs-tiQPhspt.js
vendored
Normal file
1
src/static/app/dist/assets/peerJobs-tiQPhspt.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
import{S as p,a as b}from"./schedulePeerJob-Ci8HK7bA.js";import{_ as h,W as u,z as m,k as i,a as o,c as a,b as e,d as r,w as _,F as v,h as f,i as J,e as x,T as g}from"./index-DZliHkQD.js";import{L as w}from"./localeText-DG9SnJT8.js";import"./vue-datepicker-4ltJE5cT.js";import"./dayjs.min-PaIL06iQ.js";const P={name:"peerJobs",setup(){return{store:u()}},props:{selectedPeer:Object},components:{LocaleText:w,SchedulePeerJob:p,ScheduleDropdown:b},data(){return{}},methods:{deleteJob(d){this.selectedPeer.jobs=this.selectedPeer.jobs.filter(t=>t.JobID!==d.JobID)},addJob(){this.selectedPeer.jobs.unshift(JSON.parse(JSON.stringify({JobID:m().toString(),Configuration:this.selectedPeer.configuration.Name,Peer:this.selectedPeer.id,Field:this.store.PeerScheduleJobs.dropdowns.Field[0].value,Operator:this.store.PeerScheduleJobs.dropdowns.Operator[0].value,Value:"",CreationDate:"",ExpireDate:"",Action:this.store.PeerScheduleJobs.dropdowns.Action[0].value})))}}},S={class:"peerSettingContainer w-100 h-100 position-absolute top-0 start-0 overflow-y-scroll"},y={class:"container d-flex h-100 w-100"},$={class:"m-auto modal-dialog-centered dashboardModal"},C={class:"card rounded-3 shadow",style:{width:"700px"}},D={class:"card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-2"},k={class:"mb-0 fw-normal"},j={class:"card-body px-4 pb-4 pt-2 position-relative"},T={class:"d-flex align-items-center mb-3"},N={class:"card shadow-sm",key:"none",style:{height:"153px"}},I={class:"card-body text-muted text-center d-flex"},L={class:"m-auto"};function O(d,t,B,F,V,A){const n=i("LocaleText"),l=i("SchedulePeerJob");return o(),a("div",S,[e("div",y,[e("div",$,[e("div",C,[e("div",D,[e("h4",k,[r(n,{t:"Schedule Jobs"})]),e("button",{type:"button",class:"btn-close ms-auto",onClick:t[0]||(t[0]=s=>this.$emit("close"))})]),e("div",j,[e("div",T,[e("button",{class:"btn bg-primary-subtle border-1 border-primary-subtle text-primary-emphasis rounded-3 shadow",onClick:t[1]||(t[1]=s=>this.addJob())},[t[3]||(t[3]=e("i",{class:"bi bi-plus-lg me-2"},null,-1)),r(n,{t:"Job"})])]),r(g,{name:"schedulePeerJobTransition",tag:"div",class:"position-relative"},{default:_(()=>[(o(!0),a(v,null,f(this.selectedPeer.jobs,(s,E)=>(o(),J(l,{onRefresh:t[2]||(t[2]=c=>this.$emit("refresh")),onDelete:c=>this.deleteJob(s),dropdowns:this.store.PeerScheduleJobs.dropdowns,key:s.JobID,pjob:s},null,8,["onDelete","dropdowns","pjob"]))),128)),this.selectedPeer.jobs.length===0?(o(),a("div",N,[e("div",I,[e("h6",L,[r(n,{t:"This peer does not have any job yet."})])])])):x("",!0)]),_:1})])])])])])}const q=h(P,[["render",O],["__scopeId","data-v-5bbdd42b"]]);export{q as default};
|
1
src/static/app/dist/assets/peerJobs-voXURBEt.css
vendored
Normal file
1
src/static/app/dist/assets/peerJobs-voXURBEt.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
.schedulePeerJobTransition-move[data-v-5bbdd42b],.schedulePeerJobTransition-enter-active[data-v-5bbdd42b],.schedulePeerJobTransition-leave-active[data-v-5bbdd42b]{transition:all .4s cubic-bezier(.82,.58,.17,.9)}.schedulePeerJobTransition-enter-from[data-v-5bbdd42b],.schedulePeerJobTransition-leave-to[data-v-5bbdd42b]{opacity:0;transform:scale(.9)}.schedulePeerJobTransition-leave-active[data-v-5bbdd42b]{position:absolute;width:100%}
|
1
src/static/app/dist/assets/peerJobsAllModal-BnD87caA.js
vendored
Normal file
1
src/static/app/dist/assets/peerJobsAllModal-BnD87caA.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
import{S as _}from"./schedulePeerJob-Ci8HK7bA.js";import{_ as g,W as v,k as c,a as t,c as r,b as e,d as l,F as p,h as b,t as m,e as f,i as y}from"./index-DZliHkQD.js";import{L as x}from"./localeText-DG9SnJT8.js";import"./vue-datepicker-4ltJE5cT.js";import"./dayjs.min-PaIL06iQ.js";const J={name:"peerJobsAllModal",setup(){return{store:v()}},components:{LocaleText:x,SchedulePeerJob:_},props:{configurationPeers:Array[Object]},computed:{getAllJobs(){return this.configurationPeers.filter(a=>a.jobs.length>0)}}},k={class:"peerSettingContainer w-100 h-100 position-absolute top-0 start-0 overflow-y-scroll"},w={class:"container d-flex h-100 w-100"},$={class:"m-auto modal-dialog-centered dashboardModal"},A={class:"card rounded-3 shadow",style:{width:"900px"}},L={class:"card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-2"},S={class:"mb-0 fw-normal"},C={class:"card-body px-4 pb-4 pt-2"},P={key:0,class:"accordion",id:"peerJobsLogsModalAccordion"},j={class:"accordion-header"},M=["data-bs-target"],B={key:0},N={class:"text-muted"},D=["id"],T={class:"accordion-body"},V={key:1,class:"card shadow-sm",style:{height:"153px"}},F={class:"card-body text-muted text-center d-flex"},O={class:"m-auto"};function W(a,o,E,I,R,q){const n=c("LocaleText"),u=c("SchedulePeerJob");return t(),r("div",k,[e("div",w,[e("div",$,[e("div",A,[e("div",L,[e("h4",S,[l(n,{t:"All Active Jobs"})]),e("button",{type:"button",class:"btn-close ms-auto",onClick:o[0]||(o[0]=s=>this.$emit("close"))})]),e("div",C,[e("button",{class:"btn bg-primary-subtle border-1 border-primary-subtle text-primary-emphasis rounded-3 shadow mb-2",onClick:o[1]||(o[1]=s=>this.$emit("allLogs"))},[o[4]||(o[4]=e("i",{class:"bi bi-clock me-2"},null,-1)),l(n,{t:"Logs"})]),this.getAllJobs.length>0?(t(),r("div",P,[(t(!0),r(p,null,b(this.getAllJobs,(s,d)=>(t(),r("div",{class:"accordion-item",key:s.id},[e("h2",j,[e("button",{class:"accordion-button collapsed",type:"button","data-bs-toggle":"collapse","data-bs-target":"#collapse_"+d},[e("small",null,[e("strong",null,[s.name?(t(),r("span",B,m(s.name)+" • ",1)):f("",!0),e("samp",N,m(s.id),1)])])],8,M)]),e("div",{id:"collapse_"+d,class:"accordion-collapse collapse","data-bs-parent":"#peerJobsLogsModalAccordion"},[e("div",T,[(t(!0),r(p,null,b(s.jobs,i=>(t(),y(u,{onDelete:o[2]||(o[2]=h=>this.$emit("refresh")),onRefresh:o[3]||(o[3]=h=>this.$emit("refresh")),dropdowns:this.store.PeerScheduleJobs.dropdowns,viewOnly:!0,key:i.JobID,pjob:i},null,8,["dropdowns","pjob"]))),128))])],8,D)]))),128))])):(t(),r("div",V,[e("div",F,[e("span",O,[l(n,{t:"No active job at the moment."})])])]))])])])])])}const U=g(J,[["render",W]]);export{U as default};
|
1
src/static/app/dist/assets/peerJobsLogsModal-9H0FTeh1.js
vendored
Normal file
1
src/static/app/dist/assets/peerJobsLogsModal-9H0FTeh1.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
src/static/app/dist/assets/peerList-CT7gvMs4.js
vendored
Normal file
2
src/static/app/dist/assets/peerList-CT7gvMs4.js
vendored
Normal file
File diff suppressed because one or more lines are too long
7
src/static/app/dist/assets/peerList-EJuRsJAQ.css
vendored
Normal file
7
src/static/app/dist/assets/peerList-EJuRsJAQ.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/static/app/dist/assets/peerQRCode-B62rUhHV.css
vendored
Normal file
1
src/static/app/dist/assets/peerQRCode-B62rUhHV.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
@media screen and (max-width: 768px){#qrcode[data-v-7c287bf3]{width:100%!important;height:auto!important;aspect-ratio:1/1}}
|
1
src/static/app/dist/assets/peerQRCode-Dxvodnam.js
vendored
Normal file
1
src/static/app/dist/assets/peerQRCode-Dxvodnam.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
import{b as i}from"./browser-CjSdxGTc.js";import{L as c}from"./localeText-DG9SnJT8.js";import{_ as l,D as p,g as _,k as m,a as n,c as r,b as e,d as u,n as h,e as f}from"./index-DZliHkQD.js";const g={name:"peerQRCode",components:{LocaleText:c},props:{selectedPeer:Object},setup(){return{dashboardStore:p()}},data(){return{loading:!0}},mounted(){_("/api/downloadPeer/"+this.$route.params.id,{id:this.selectedPeer.id},o=>{if(this.loading=!1,o.status){let t="";if(this.selectedPeer.configuration.Protocol==="awg"){let a={containers:[{awg:{isThirdPartyConfig:!0,last_config:o.data.file,port:this.selectedPeer.configuration.ListenPort,transport_proto:"udp"},container:"amnezia-awg"}],defaultContainer:"amnezia-awg",description:this.selectedPeer.name,hostName:this.dashboardStore.Configuration.Peers.remote_endpoint};t=btoa(JSON.stringify(a))}else t=o.data.file;i.toCanvas(document.querySelector("#qrcode"),t,a=>{a&&console.error(a)})}else this.dashboardStore.newMessage("Server",o.message,"danger")})}},b={class:"peerSettingContainer w-100 h-100 position-absolute top-0 start-0"},v={class:"container d-flex h-100 w-100"},C={class:"m-auto modal-dialog-centered dashboardModal justify-content-center"},w={class:"card rounded-3 shadow"},P={class:"card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-0"},x={class:"mb-0"},S={class:"card-body p-4"},y={class:"d-flex"},L={key:0,class:"spinner-border m-auto",role:"status"};function k(o,t,a,N,s,$){const d=m("LocaleText");return n(),r("div",b,[e("div",v,[e("div",C,[e("div",w,[e("div",P,[e("h4",x,[u(d,{t:"QR Code"})]),e("button",{type:"button",class:"btn-close ms-auto",onClick:t[0]||(t[0]=Q=>this.$emit("close"))})]),e("div",S,[e("div",y,[e("canvas",{id:"qrcode",class:h(["rounded-3 shadow animate__animated animate__fadeIn animate__faster",{"d-none":s.loading}])},null,2),s.loading?(n(),r("div",L,t[1]||(t[1]=[e("span",{class:"visually-hidden"},"Loading...",-1)]))):f("",!0)])])])])])])}const q=l(g,[["render",k],["__scopeId","data-v-7c287bf3"]]);export{q as default};
|
1
src/static/app/dist/assets/peerSearchBar-BrbvrjWX.css
vendored
Normal file
1
src/static/app/dist/assets/peerSearchBar-BrbvrjWX.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
.searchPeersContainer[data-v-b741afe7]{width:100%}
|
1
src/static/app/dist/assets/peerSearchBar-JmFRkc04.js
vendored
Normal file
1
src/static/app/dist/assets/peerSearchBar-JmFRkc04.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
import{_ as u,q as m,G as p,r as b,W as f,a2 as h,o as g,a as v,i as y,w as _,b as e,m as x,y as w,d as S,j as B}from"./index-DZliHkQD.js";import{L as T}from"./localeText-DG9SnJT8.js";const C={class:"fixed-bottom w-100 bottom-0 z-2",style:{"z-index":"1"}},P={class:"container-fluid"},k={class:"row g-0"},L={class:"col-md-9 col-lg-10 d-flex justify-content-center py-2"},V={class:"rounded-3 p-2 border shadow searchPeersContainer bg-body-tertiary"},j={class:"d-flex gap-1 align-items-center px-2"},z=["placeholder"],D={__name:"peerSearchBar",emits:["close"],setup(G,{emit:n}){const l=m(()=>p("Search Peers..."));let t;const o=b(""),r=f(),i=()=>{t?(clearTimeout(t),t=setTimeout(()=>{r.searchString=o.value},300)):t=setTimeout(()=>{r.searchString=o.value},300)},d=n,c=h("searchBar");return g(()=>{c.value.focus()}),(M,s)=>(v(),y(B,{name:"slideUp",appear:"",type:"animation",style:{"animation-delay":"1s"}},{default:_(()=>[e("div",C,[e("div",P,[e("div",k,[s[5]||(s[5]=e("div",{class:"col-md-3 col-lg-2"},null,-1)),e("div",L,[e("div",V,[e("div",j,[s[4]||(s[4]=e("h6",{class:"mb-0 me-2"},[e("label",{for:"searchPeers"},[e("i",{class:"bi bi-search"})])],-1)),x(e("input",{ref:"searchBar",class:"flex-grow-1 form-control rounded-3 bg-secondary-subtle border-1 border-secondary-subtle",placeholder:l.value,id:"searchPeers",onKeyup:s[0]||(s[0]=a=>i()),"onUpdate:modelValue":s[1]||(s[1]=a=>o.value=a)},null,40,z),[[w,o.value]]),e("button",{onClick:s[2]||(s[2]=a=>d("close")),style:{"white-space":"nowrap"},class:"btn bg-secondary-subtle text-secondary-emphasis border-secondary-subtle rounded-3 d-flex align-items-center"},[e("span",null,[s[3]||(s[3]=e("i",{class:"bi bi-x-circle-fill me-2"},null,-1)),S(T,{t:"Done"})])])])])])])])])]),_:1}))}},W=u(D,[["__scopeId","data-v-b741afe7"]]);export{W as default};
|
1
src/static/app/dist/assets/peerSettings-BkfvIQvk.css
vendored
Normal file
1
src/static/app/dist/assets/peerSettings-BkfvIQvk.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
.toggleShowKey[data-v-12b3ae8e]{position:absolute;top:35px;right:12px}
|
1
src/static/app/dist/assets/peerSettings-Bne_y8f7.js
vendored
Normal file
1
src/static/app/dist/assets/peerSettings-Bne_y8f7.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/static/app/dist/assets/peerShareLinkModal-Cl59KMsF.js
vendored
Normal file
1
src/static/app/dist/assets/peerShareLinkModal-Cl59KMsF.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/static/app/dist/assets/peerShareLinkModal-ouYxVldA.css
vendored
Normal file
1
src/static/app/dist/assets/peerShareLinkModal-ouYxVldA.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
.card[data-v-8cfb4d4d]{border-color:var(--bs-border-color)!important}textarea[data-v-6e705c87]:focus,input[data-v-6e705c87]:focus{box-shadow:none;border-color:var(--bs-border-color)!important}textarea[data-v-6e705c87]{padding:var(--bs-card-spacer-y) var(--bs-card-spacer-x)}
|
1
src/static/app/dist/assets/ping-CrzXKpFV.js
vendored
Normal file
1
src/static/app/dist/assets/ping-CrzXKpFV.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/static/app/dist/assets/ping-DojRH9NX.css
vendored
Normal file
1
src/static/app/dist/assets/ping-DojRH9NX.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
.pingPlaceholder[data-v-a08ce97e]{width:100%;height:79.98px}.ping-move[data-v-a08ce97e],.ping-enter-active[data-v-a08ce97e],.ping-leave-active[data-v-a08ce97e]{transition:all .4s cubic-bezier(.82,.58,.17,.9)}.ping-leave-active[data-v-a08ce97e]{position:absolute;width:100%}.ping-enter-from[data-v-a08ce97e],.ping-leave-to[data-v-a08ce97e]{opacity:0;filter:blur(3px)}
|
1
src/static/app/dist/assets/protocolBadge-rpLx04Ri.js
vendored
Normal file
1
src/static/app/dist/assets/protocolBadge-rpLx04Ri.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
import{L as r}from"./localeText-DG9SnJT8.js";import{a as t,c as n,f as i,i as s,e as a}from"./index-DZliHkQD.js";const d={key:0,class:"badge wireguardBg rounded-3 shadow"},c={key:1,class:"badge amneziawgBg rounded-3 shadow"},u={__name:"protocolBadge",props:{protocol:String,mini:!1},setup(e){return(m,o)=>e.protocol==="wg"?(t(),n("span",d,[o[0]||(o[0]=i(" WireGuard ")),e.mini?a("",!0):(t(),s(r,{key:0,t:"Configuration"}))])):e.protocol==="awg"?(t(),n("span",c,[o[1]||(o[1]=i(" AmneziaWG ")),e.mini?a("",!0):(t(),s(r,{key:0,t:"Configuration"}))])):a("",!0)}};export{u as _};
|
4
src/static/app/dist/assets/restoreConfiguration-CNCGDtFu.js
vendored
Normal file
4
src/static/app/dist/assets/restoreConfiguration-CNCGDtFu.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/static/app/dist/assets/restoreConfiguration-VgIx_N7z.css
vendored
Normal file
1
src/static/app/dist/assets/restoreConfiguration-VgIx_N7z.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
.dropdownIcon[data-v-ccf48ac7]{transition:all .2s ease-in-out}.dropdownIcon.active[data-v-ccf48ac7]{transform:rotate(180deg)}.steps{&[data-v-324df2b1]{transition:all .3s ease-in-out;opacity:.3}&.active[data-v-324df2b1]{opacity:1}}
|
1
src/static/app/dist/assets/schedulePeerJob-Ci8HK7bA.js
vendored
Normal file
1
src/static/app/dist/assets/schedulePeerJob-Ci8HK7bA.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/static/app/dist/assets/schedulePeerJob-DPy59wup.css
vendored
Normal file
1
src/static/app/dist/assets/schedulePeerJob-DPy59wup.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
.btn.disabled[data-v-6a5aba2a]{opacity:1;background-color:#0d6efd17;border-color:transparent}[data-v-4aa63a3e]{font-size:.875rem}input[data-v-4aa63a3e]{padding:.1rem .4rem}input[data-v-4aa63a3e]:disabled{border-color:transparent;background-color:#0d6efd17;color:#0d6efd}.dp__main[data-v-4aa63a3e]{width:auto;flex-grow:1;--dp-input-padding: 2.5px 30px 2.5px 12px;--dp-border-radius: .5rem}
|
1
src/static/app/dist/assets/selectPeers-7CTijh1V.js
vendored
Normal file
1
src/static/app/dist/assets/selectPeers-7CTijh1V.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/static/app/dist/assets/selectPeers-Wjnh8YUZ.css
vendored
Normal file
1
src/static/app/dist/assets/selectPeers-Wjnh8YUZ.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
.card[data-v-177407c1]{height:100%}.dashboardModal[data-v-177407c1]{height:calc(100% - 1rem)!important}@media screen and (min-height: 700px){.card[data-v-177407c1]{height:700px}}.peerBtn[data-v-177407c1]{border:var(--bs-border-width) solid var(--bs-border-color)}.peerBtn.active[data-v-177407c1]{border:var(--bs-border-width) solid var(--bs-body-color)}
|
1
src/static/app/dist/assets/settings-CrxzSFju.js
vendored
Normal file
1
src/static/app/dist/assets/settings-CrxzSFju.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/static/app/dist/assets/settings-DbQs6Bt_.css
vendored
Normal file
1
src/static/app/dist/assets/settings-DbQs6Bt_.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
@media screen and (max-width: 992px){.apiKey-card-body{&[data-v-a76253c8]{flex-direction:column!important;align-items:start!important}div.ms-auto[data-v-a76253c8]{margin-left:0!important}div[data-v-a76253c8]{width:100%;align-items:start!important}small[data-v-a76253c8]{margin-right:auto}}}.apiKey-move[data-v-100ee9f9],.apiKey-enter-active[data-v-100ee9f9],.apiKey-leave-active[data-v-100ee9f9]{transition:all .5s ease}.apiKey-enter-from[data-v-100ee9f9],.apiKey-leave-to[data-v-100ee9f9]{opacity:0;transform:translateY(30px) scale(.9)}.apiKey-leave-active[data-v-100ee9f9]{position:absolute;width:100%}.dropdown-menu[data-v-4e34593e]{width:100%}.list-group{&[data-v-4aa2aed9]:first-child{border-top-left-radius:var(--bs-border-radius-lg);border-top-right-radius:var(--bs-border-radius-lg)}&[data-v-4aa2aed9]:last-child{border-bottom-left-radius:var(--bs-border-radius-lg);border-bottom-right-radius:var(--bs-border-radius-lg)}}
|
1
src/static/app/dist/assets/setup-BmUSkunY.js
vendored
Normal file
1
src/static/app/dist/assets/setup-BmUSkunY.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
import{_ as u,D as m,A as p,c as r,b as e,d as o,f as c,t as h,e as f,m as l,y as d,a as i,k as w}from"./index-DZliHkQD.js";import{L as g}from"./localeText-DG9SnJT8.js";const b={name:"setup",components:{LocaleText:g},setup(){return{store:m()}},data(){return{setup:{username:"",newPassword:"",repeatNewPassword:"",enable_totp:!0},loading:!1,errorMessage:"",done:!1}},computed:{goodToSubmit(){return this.setup.username&&this.setup.newPassword.length>=8&&this.setup.repeatNewPassword.length>=8&&this.setup.newPassword===this.setup.repeatNewPassword}},methods:{submit(){this.loading=!0,p("/api/Welcome_Finish",this.setup,n=>{n.status?(this.done=!0,this.$router.push("/2FASetup")):(document.querySelectorAll("#createAccount input").forEach(s=>s.classList.add("is-invalid")),this.errorMessage=n.message,document.querySelector(".login-container-fluid").scrollTo({top:0,left:0,behavior:"smooth"})),this.loading=!1})}}},_=["data-bs-theme"],x={class:"m-auto text-body",style:{width:"500px"}},v={class:"dashboardLogo display-4"},y={class:"mb-5"},P={key:0,class:"alert alert-danger"},N={class:"d-flex flex-column gap-3"},k={id:"createAccount",class:"d-flex flex-column gap-2"},S={class:"form-group text-body"},T={for:"username",class:"mb-1 text-muted"},C={class:"form-group text-body"},L={for:"password",class:"mb-1 text-muted"},V={class:"form-group text-body"},A={for:"confirmPassword",class:"mb-1 text-muted"},$=["disabled"],q={key:0,class:"d-flex align-items-center w-100"},M={key:1,class:"d-flex align-items-center w-100"};function B(n,s,D,E,U,F){const t=w("LocaleText");return i(),r("div",{class:"container-fluid login-container-fluid d-flex main pt-5 overflow-scroll","data-bs-theme":this.store.Configuration.Server.dashboard_theme},[e("div",x,[e("span",v,[o(t,{t:"Nice to meet you!"})]),e("p",y,[o(t,{t:"Please fill in the following fields to finish setup"}),s[4]||(s[4]=c(" 😊"))]),e("div",null,[e("h3",null,[o(t,{t:"Create an account"})]),this.errorMessage?(i(),r("div",P,h(this.errorMessage),1)):f("",!0),e("div",N,[e("form",k,[e("div",S,[e("label",T,[e("small",null,[o(t,{t:"Enter an username you like"})])]),l(e("input",{type:"text",autocomplete:"username","onUpdate:modelValue":s[0]||(s[0]=a=>this.setup.username=a),class:"form-control",id:"username",name:"username",required:""},null,512),[[d,this.setup.username]])]),e("div",C,[e("label",L,[e("small",null,[o(t,{t:"Enter a password"}),e("code",null,[o(t,{t:"(At least 8 characters and make sure is strong enough!)"})])])]),l(e("input",{type:"password",autocomplete:"new-password","onUpdate:modelValue":s[1]||(s[1]=a=>this.setup.newPassword=a),class:"form-control",id:"password",name:"password",required:""},null,512),[[d,this.setup.newPassword]])]),e("div",V,[e("label",A,[e("small",null,[o(t,{t:"Confirm password"})])]),l(e("input",{type:"password",autocomplete:"confirm-new-password","onUpdate:modelValue":s[2]||(s[2]=a=>this.setup.repeatNewPassword=a),class:"form-control",id:"confirmPassword",name:"confirmPassword",required:""},null,512),[[d,this.setup.repeatNewPassword]])])]),e("button",{class:"btn btn-dark btn-lg mb-5 d-flex btn-brand shadow align-items-center",ref:"signInBtn",disabled:!this.goodToSubmit||this.loading||this.done,onClick:s[3]||(s[3]=a=>this.submit())},[!this.loading&&!this.done?(i(),r("span",q,[o(t,{t:"Next"}),s[5]||(s[5]=e("i",{class:"bi bi-chevron-right ms-auto"},null,-1))])):(i(),r("span",M,[o(t,{t:"Saving..."}),s[6]||(s[6]=e("span",{class:"spinner-border ms-auto spinner-border-sm",role:"status"},[e("span",{class:"visually-hidden"},"Loading...")],-1))]))],8,$)])])])],8,_)}const j=u(b,[["render",B]]);export{j as default};
|
1
src/static/app/dist/assets/share-B4McccvP.css
vendored
Normal file
1
src/static/app/dist/assets/share-B4McccvP.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
.animate__fadeInUp[data-v-1b44aacd]{animation-timing-function:cubic-bezier(.42,0,.22,1)}
|
1
src/static/app/dist/assets/share-CsPN7pXl.js
vendored
Normal file
1
src/static/app/dist/assets/share-CsPN7pXl.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
import{_,r,D as p,g as u,c as m,b as t,d as c,J as h,a as f,k as b}from"./index-DZliHkQD.js";import{b as v}from"./browser-CjSdxGTc.js";import{L as y}from"./localeText-DG9SnJT8.js";const g={name:"share",components:{LocaleText:y},async setup(){const o=h(),e=r(!1),i=p(),n=r(""),s=r(void 0),l=r(new Blob);await u("/api/getDashboardTheme",{},d=>{n.value=d.data});const a=o.query.ShareID;return a===void 0||a.length===0?(s.value=void 0,e.value=!0):await u("/api/sharePeer/get",{ShareID:a},d=>{d.status?(s.value=d.data,l.value=new Blob([s.value.file],{type:"text/plain"})):s.value=void 0,e.value=!0}),{store:i,theme:n,peerConfiguration:s,blob:l}},mounted(){this.peerConfiguration&&v.toCanvas(document.querySelector("#qrcode"),this.peerConfiguration.file,o=>{o&&console.error(o)})},methods:{download(){const o=new Blob([this.peerConfiguration.file],{type:"text/plain"}),e=URL.createObjectURL(o),i=`${this.peerConfiguration.fileName}.conf`,n=document.createElement("a");n.href=e,n.download=i,n.click()}},computed:{getBlob(){return URL.createObjectURL(this.blob)}}},w=["data-bs-theme"],x={class:"m-auto text-body",style:{width:"500px"}},C={key:0,class:"text-center position-relative",style:{}},U={class:"position-absolute w-100 h-100 top-0 start-0 d-flex animate__animated animate__fadeInUp",style:{"animation-delay":"0.1s"}},I={class:"m-auto"},L={key:1,class:"d-flex align-items-center flex-column gap-3"},k={class:"h1 dashboardLogo text-center animate__animated animate__fadeInUp"},B={id:"qrcode",class:"rounded-3 shadow animate__animated animate__fadeInUp mb-3",ref:"qrcode"},D={class:"text-muted animate__animated animate__fadeInUp mb-1",style:{"animation-delay":"0.2s"}},R=["download","href"];function q(o,e,i,n,s,l){const a=b("LocaleText");return f(),m("div",{class:"container-fluid login-container-fluid d-flex main pt-5 overflow-scroll","data-bs-theme":this.theme},[t("div",x,[this.peerConfiguration?(f(),m("div",L,[t("div",k,[e[1]||(e[1]=t("h6",null,"WGDashboard",-1)),c(a,{t:"Scan QR Code with the WireGuard App to add peer"})]),t("canvas",B,null,512),t("p",D,[c(a,{t:"or click the button below to download the "}),e[2]||(e[2]=t("samp",null,".conf",-1)),c(a,{t:" file"})]),t("a",{download:this.peerConfiguration.fileName+".conf",href:l.getBlob,class:"btn btn-lg bg-primary-subtle text-primary-emphasis border-1 border-primary-subtle animate__animated animate__fadeInUp shadow-sm",style:{"animation-delay":"0.25s"}},e[3]||(e[3]=[t("i",{class:"bi bi-download"},null,-1)]),8,R)])):(f(),m("div",C,[e[0]||(e[0]=t("div",{class:"animate__animated animate__fadeInUp"},[t("h1",{style:{"font-size":"20rem",filter:"blur(1rem)","animation-duration":"7s"},class:"animate__animated animate__flash animate__infinite"},[t("i",{class:"bi bi-file-binary"})])],-1)),t("div",U,[t("h3",I,[c(a,{t:"Oh no... This link is either expired or invalid."})])])]))])],8,w)}const N=_(g,[["render",q],["__scopeId","data-v-1b44aacd"]]);export{N as default};
|
1
src/static/app/dist/assets/signin-BKQo1OCC.js
vendored
Normal file
1
src/static/app/dist/assets/signin-BKQo1OCC.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/static/app/dist/assets/signin-CHulm0U0.css
vendored
Normal file
1
src/static/app/dist/assets/signin-CHulm0U0.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
.dot.inactive[data-v-ed7817c7]{background-color:#dc3545;box-shadow:0 0 0 .2rem #dc354545}.spin[data-v-ed7817c7]{animation:spin-ed7817c7 1s infinite cubic-bezier(.82,.58,.17,.9)}@keyframes spin-ed7817c7{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@media screen and (max-width: 768px){.remoteServerContainer[data-v-ed7817c7]{flex-direction:column}.remoteServerContainer .button-group button[data-v-ed7817c7]{width:100%}}@media screen and (max-width: 768px){.login-box[data-v-80e20da4]{width:100%!important}.login-box div[data-v-80e20da4]{width:auto!important}}
|
1
src/static/app/dist/assets/storageMount-Bl6vLa1N.css
vendored
Normal file
1
src/static/app/dist/assets/storageMount-Bl6vLa1N.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
.square[data-v-2ad535bb]{height:var(--2ec4d3bc);transition:background-color .5s cubic-bezier(.42,0,.22,1)}.square[data-v-9509d7a0]{height:var(--2dc8ab7e);transition:background-color .5s cubic-bezier(.42,0,.22,1)}
|
@ -0,0 +1 @@
|
||||
import{_ as b,p as m,r as p,q as v,a as t,c as r,d as g,w as x,s as n,n as f,b as l,t as d,e as C,j as w}from"./index-DZliHkQD.js";const y={class:"text-muted me-2"},_={class:"fw-bold"},k={__name:"cpuCore",props:{core_number:Number,percentage:Number,align:Boolean,square:Boolean},setup(e){m(c=>({"2ec4d3bc":o.value}));const u=e,s=p(!1),o=v(()=>u.square?"40px":"25px");return(c,a)=>(t(),r("div",{class:"flex-grow-1 square rounded-3 border position-relative p-2",onMouseenter:a[0]||(a[0]=i=>s.value=!0),onMouseleave:a[1]||(a[1]=i=>s.value=!1),style:n({"background-color":`rgb(13 110 253 / ${e.percentage*10}%)`})},[g(w,{name:"zoomReversed"},{default:x(()=>[s.value?(t(),r("div",{key:0,style:n([{"white-space":"nowrap"},{top:o.value}]),class:f(["floatingLabel z-3 border position-absolute d-block p-1 px-2 bg-body text-body rounded-3 border shadow d-flex",[e.align?"end-0":"start-0"]])},[l("small",y," Core #"+d(e.core_number+1),1),l("small",_,d(e.percentage)+"% ",1)],6)):C("",!0)]),_:1})],36))}},B=b(k,[["__scopeId","data-v-2ad535bb"]]);export{B as C};
|
1
src/static/app/dist/assets/systemStatus-C-kMgV1x.css
vendored
Normal file
1
src/static/app/dist/assets/systemStatus-C-kMgV1x.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
.title[data-v-ffe5ad8f]{height:18px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.process-move[data-v-977dc46d],.process-enter-active[data-v-977dc46d],.process-leave-active[data-v-977dc46d]{transition:all .5s cubic-bezier(.42,0,.22,1)}.process-enter-from[data-v-977dc46d],.process-leave-to[data-v-977dc46d]{opacity:0;transform:scale(.9)}.process-leave-active[data-v-977dc46d]{position:absolute;width:100%}.progress-bar[data-v-977dc46d]{width:0;transition:all 1s cubic-bezier(.42,0,.22,1)}.fadeIn[data-v-977dc46d]{opacity:0;animation:fadeIn-977dc46d .5s forwards cubic-bezier(.42,0,.22,1)}@keyframes fadeIn-977dc46d{0%{opacity:0;transform:translateY(30px)}to{opacity:1;transform:translateY(0)}}
|
1
src/static/app/dist/assets/systemStatus-DHmERTYR.js
vendored
Normal file
1
src/static/app/dist/assets/systemStatus-DHmERTYR.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
src/static/app/dist/assets/totp-G9lM0GPx.js
vendored
Normal file
1
src/static/app/dist/assets/totp-G9lM0GPx.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
import{_ as h,D as m,g as p,A as f,c as b,b as t,d as i,t as _,m as v,y as g,i as d,w as r,k as c,a as n}from"./index-DZliHkQD.js";import{b as x}from"./browser-CjSdxGTc.js";import{L as y}from"./localeText-DG9SnJT8.js";const T={name:"totp",components:{LocaleText:y},async setup(){const s=m();let e="";return await p("/api/Welcome_GetTotpLink",{},a=>{a.status&&(e=a.data)}),{l:e,store:s}},mounted(){this.l&&x.toCanvas(document.getElementById("qrcode"),this.l,function(s){})},data(){return{totp:"",totpInvalidMessage:"",verified:!1}},methods:{validateTotp(){}},watch:{totp(s){const e=document.querySelector("#totp");e.classList.remove("is-invalid","is-valid"),s.length===6&&(console.log(s),/[0-9]{6}/.test(s)?f("/api/Welcome_VerifyTotpLink",{totp:s},a=>{a.status?(this.verified=!0,e.classList.add("is-valid"),this.$emit("verified")):(e.classList.add("is-invalid"),this.totpInvalidMessage="TOTP does not match.")}):(e.classList.add("is-invalid"),this.totpInvalidMessage="TOTP can only contain numbers"))}}},k=["data-bs-theme"],w={class:"m-auto text-body",style:{width:"500px"}},L={class:"d-flex flex-column"},M={class:"dashboardLogo display-4"},C={class:"mb-2"},P={class:"text-muted"},I={class:"p-3 bg-body-secondary rounded-3 border mb-3"},O={class:"text-muted mb-0"},B=["href"],$={style:{"line-break":"anywhere"}},A={for:"totp",class:"mb-2"},D={class:"text-muted"},S={class:"form-group mb-2"},q=["disabled"],E={class:"invalid-feedback"},F={class:"valid-feedback"},R={class:"d-flex gap-3 mt-5 flex-column"};function G(s,e,a,N,W,Q){const o=c("LocaleText"),l=c("RouterLink");return n(),b("div",{class:"container-fluid login-container-fluid d-flex main pt-5 overflow-scroll","data-bs-theme":this.store.Configuration.Server.dashboard_theme},[t("div",w,[t("div",L,[t("div",null,[t("h1",M,[i(o,{t:"Multi-Factor Authentication (MFA)"})]),t("p",C,[t("small",P,[i(o,{t:"1. Please scan the following QR Code to generate TOTP with your choice of authenticator"})])]),e[1]||(e[1]=t("canvas",{id:"qrcode",class:"rounded-3 mb-2"},null,-1)),t("div",I,[t("p",O,[t("small",null,[i(o,{t:"Or you can click the link below:"})])]),t("a",{href:this.l},[t("code",$,_(this.l),1)],8,B)]),t("label",A,[t("small",D,[i(o,{t:"2. Enter the TOTP generated by your authenticator to verify"})])]),t("div",S,[v(t("input",{class:"form-control text-center totp",id:"totp",maxlength:"6",type:"text",inputmode:"numeric",autocomplete:"one-time-code","onUpdate:modelValue":e[0]||(e[0]=u=>this.totp=u),disabled:this.verified},null,8,q),[[g,this.totp]]),t("div",E,[i(o,{t:this.totpInvalidMessage},null,8,["t"])]),t("div",F,[i(o,{t:"TOTP verified!"})])])]),e[4]||(e[4]=t("hr",null,null,-1)),t("div",R,[this.verified?(n(),d(l,{key:1,to:"/",class:"btn btn-dark btn-lg d-flex btn-brand shadow align-items-center flex-grow-1 rounded-3"},{default:r(()=>[i(o,{t:"Complete"}),e[3]||(e[3]=t("i",{class:"bi bi-chevron-right ms-auto"},null,-1))]),_:1})):(n(),d(l,{key:0,to:"/",class:"btn bg-secondary-subtle text-secondary-emphasis rounded-3 flex-grow-1 btn-lg border-1 border-secondary-subtle shadow d-flex"},{default:r(()=>[i(o,{t:"I don't need MFA"}),e[2]||(e[2]=t("i",{class:"bi bi-chevron-right ms-auto"},null,-1))]),_:1}))])])])],8,k)}const z=h(T,[["render",G]]);export{z as default};
|
1
src/static/app/dist/assets/traceroute-Bd2NnUB2.js
vendored
Normal file
1
src/static/app/dist/assets/traceroute-Bd2NnUB2.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
import{_ as h,W as g,g as b,c as o,b as t,d as n,m as y,y as f,C as x,w as r,j as c,a as l,f as v,F as u,h as m,n as k,s as T,t as i,k as _}from"./index-DZliHkQD.js";import{O as A}from"./osmap-CmjRjQ0N.js";import{L as w}from"./localeText-DG9SnJT8.js";const R={name:"traceroute",components:{LocaleText:w,OSMap:A},data(){return{tracing:!1,ipAddress:void 0,tracerouteResult:void 0}},setup(){return{store:g()}},methods:{execute(){this.ipAddress&&(this.tracing=!0,this.tracerouteResult=void 0,b("/api/traceroute/execute",{ipAddress:this.ipAddress},d=>{d.status?this.tracerouteResult=d.data:this.store.newMessage("Server",d.message,"danger"),this.tracing=!1}))}}},M={class:"mt-md-5 mt-3 text-body"},S={class:"container-md"},$={class:"mb-3 text-body"},C={class:"d-flex gap-2 mb-3 flex-column"},L={class:"flex-grow-1"},P={class:"mb-1 text-muted",for:"ipAddress"},O=["disabled"],V=["disabled"],B={key:0,class:"d-block"},I={key:1,class:"d-block"},N={class:"position-relative"},z={key:"pingPlaceholder"},D={key:1},E={key:"table",class:"w-100 mt-2"},F={class:"table table-sm rounded-3 w-100"},G={scope:"col"},H={scope:"col"},K={scope:"col"},W={scope:"col"},j={scope:"col"},U={scope:"col"},q={key:0},J={key:1};function Q(d,s,X,Y,Z,tt){const a=_("LocaleText"),p=_("OSMap");return l(),o("div",M,[t("div",S,[t("h3",$,[n(a,{t:"Traceroute"})]),t("div",C,[t("div",L,[t("label",P,[t("small",null,[n(a,{t:"Enter IP Address / Hostname"})])]),y(t("input",{disabled:this.tracing,id:"ipAddress",class:"form-control rounded-3","onUpdate:modelValue":s[0]||(s[0]=e=>this.ipAddress=e),onKeyup:s[1]||(s[1]=x(e=>this.execute(),["enter"])),type:"text"},null,40,O),[[f,this.ipAddress]])]),t("button",{class:"btn btn-primary rounded-3 position-relative flex-grow-1",disabled:this.tracing||!this.ipAddress,onClick:s[2]||(s[2]=e=>this.execute())},[n(c,{name:"slide"},{default:r(()=>[this.tracing?(l(),o("span",I,s[4]||(s[4]=[t("span",{class:"spinner-border spinner-border-sm","aria-hidden":"true"},null,-1),t("span",{class:"visually-hidden",role:"status"},"Loading...",-1)]))):(l(),o("span",B,s[3]||(s[3]=[t("i",{class:"bi bi-person-walking me-2"},null,-1),v("Trace! ")])))]),_:1})],8,V)]),t("div",N,[n(c,{name:"ping"},{default:r(()=>[this.tracerouteResult?(l(),o("div",D,[n(p,{d:this.tracerouteResult,type:"traceroute"},null,8,["d"]),t("div",E,[t("table",F,[t("thead",null,[t("tr",null,[t("th",G,[n(a,{t:"Hop"})]),t("th",H,[n(a,{t:"IP Address"})]),t("th",K,[n(a,{t:"Average RTT (ms)"})]),t("th",W,[n(a,{t:"Min RTT (ms)"})]),t("th",j,[n(a,{t:"Max RTT (ms)"})]),t("th",U,[n(a,{t:"Geolocation"})])])]),t("tbody",null,[(l(!0),o(u,null,m(this.tracerouteResult,(e,et)=>(l(),o("tr",null,[t("td",null,[t("small",null,i(e.hop),1)]),t("td",null,[t("small",null,[t("samp",null,i(e.ip),1)])]),t("td",null,[t("small",null,[t("samp",null,i(e.avg_rtt),1)])]),t("td",null,[t("small",null,[t("samp",null,i(e.min_rtt),1)])]),t("td",null,[t("small",null,[t("samp",null,i(e.max_rtt),1)])]),t("td",null,[e.geo.city&&e.geo.country?(l(),o("span",q,[t("small",null,i(e.geo.city)+", "+i(e.geo.country),1)])):(l(),o("span",J," - "))])]))),256))])])])])):(l(),o("div",z,[s[5]||(s[5]=t("div",{class:"pingPlaceholder bg-body-secondary rounded-3 mb-3",style:{height:"300px !important"}},null,-1)),(l(),o(u,null,m(5,e=>t("div",{class:k(["pingPlaceholder bg-body-secondary rounded-3 mb-3",{"animate__animated animate__flash animate__slower animate__infinite":this.tracing}]),style:T({"animation-delay":`${e*.05}s`})},null,6)),64))]))]),_:1})])])])}const lt=h(R,[["render",Q],["__scopeId","data-v-3e75b4d4"]]);export{lt as default};
|
1
src/static/app/dist/assets/traceroute-DH1nb6XH.css
vendored
Normal file
1
src/static/app/dist/assets/traceroute-DH1nb6XH.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
.pingPlaceholder[data-v-3e75b4d4]{width:100%;height:40px}.ping-move[data-v-3e75b4d4],.ping-enter-active[data-v-3e75b4d4],.ping-leave-active[data-v-3e75b4d4]{transition:all .4s cubic-bezier(.82,.58,.17,.9)}.ping-leave-active[data-v-3e75b4d4]{position:absolute;width:100%}.ping-enter-from[data-v-3e75b4d4],.ping-leave-to[data-v-3e75b4d4]{opacity:0;filter:blur(3px)}.ping-leave-active[data-v-3e75b4d4]{position:absolute}table th[data-v-3e75b4d4],table td[data-v-3e75b4d4]{padding:.5rem}.table[data-v-3e75b4d4]>:not(caption)>*>*{background-color:transparent!important}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user