Compare commits
1396 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1abd669de5 | |||
| ac9df2fc08 | |||
| eba24b9242 | |||
| edd61705dc | |||
| 3f20e29901 | |||
| 36ae162626 | |||
| 00f7cb9dbb | |||
| 1ca3dc26eb | |||
| 2f3be267b3 | |||
| 5b8f6910fb | |||
| 9fe26ba814 | |||
| 5e97ed1c7e | |||
| 947fb7af7a | |||
| 44bcc157e5 | |||
| 278bf3da13 | |||
| 446bc81d3a | |||
| 9527aac242 | |||
| c57f1f9d7d | |||
| e372527d13 | |||
| 96be1e1275 | |||
| 8ce17d0585 | |||
| 6af1eaa4e4 | |||
| da01487301 | |||
| 708d7b5fc5 | |||
| 62b5a159a9 | |||
| a6d04509a5 | |||
| 0071596274 | |||
| 59f66051f8 | |||
| 9f1e59cf78 | |||
| f1f68b8ef6 | |||
| f22c3cdda9 | |||
| 5e15cc3bbe | |||
| a6690493b0 | |||
| 17a6335d13 | |||
| ca57f6de85 | |||
| aefaabdb1a | |||
| 9211c8d3b1 | |||
| eff1980df5 | |||
| 1553ba5630 | |||
| ec24120d2a | |||
| 50df750202 | |||
| dab4aced48 | |||
| 1774952312 | |||
| d66d6e70a6 | |||
| 4635e9269d | |||
| 574867536d | |||
| 5488a4d118 | |||
| e34f3c7c2c | |||
| ceaff7b645 | |||
| d27a025347 | |||
| 2b2853a183 | |||
| a25263f868 | |||
| 4b9727067b | |||
| 00fc392a12 | |||
| 1da90fe1ec | |||
| 25ba50d6f7 | |||
| f22e99aec8 | |||
| f027fd5f21 | |||
| 37a038c24f | |||
| 3a8f825de5 | |||
| d2df83cf2f | |||
| d481850d4c | |||
| 6c55e2bd9d | |||
| 2fd357c346 | |||
| 0a5e58201a | |||
| d687b20467 | |||
| 7dbcedad40 | |||
| b6e8d28ed3 | |||
| 85ce47f5bb | |||
| 55c98cc27a | |||
| 422f3ec81e | |||
| 54fb91c03b | |||
| 6df9742664 | |||
| f23a221750 | |||
| 4637accb51 | |||
| 74f067d893 | |||
| 43773954cd | |||
| 30cafef9f2 | |||
| 251f2d82b3 | |||
| e905550778 | |||
| adee99db34 | |||
| eda2eb2283 | |||
| a7123a04ba | |||
| 8a562f1d15 | |||
| d4861a74df | |||
| 8971cc4b8b | |||
| bca6dd41d2 | |||
| 221c4eeb0c | |||
| bbb1fbfbe8 | |||
| 5a874a90ac | |||
| 1c14c2fdef | |||
| 73a038afd4 | |||
| 4d55765e28 | |||
| 2b43f3cb84 | |||
| 52c4885335 | |||
| aa5fe52e89 | |||
| ce107dd688 | |||
| 72affd7a5b | |||
| ba4c51dd68 | |||
| 294fb1f774 | |||
| a846afe733 | |||
| 5fb3cea0bb | |||
| 4ae89c23cd | |||
| 3d32fe662b | |||
| 468674a517 | |||
| ebe4354a85 | |||
| f47bc5ea7d | |||
| 427615f627 | |||
| 829b560794 | |||
| f97a15c5c3 | |||
| 25fcf523e3 | |||
| c1be94c4ad | |||
| 3a05d72124 | |||
| 7ec44e46ce | |||
| 060b17df01 | |||
| 74c78d7577 | |||
| 1ef0c1adac | |||
| c2e649e2bf | |||
| 196db9718e | |||
| 9f5b264e04 | |||
| 3825f5fb61 | |||
| e60dbc883c | |||
| bbbfa91db9 | |||
| 5ec8e2da66 | |||
| 9e59bd5687 | |||
| 1d26ccac4e | |||
| 0e2526f627 | |||
| dd9e9c7a6d | |||
| e19922abd0 | |||
| d27bde6047 | |||
| 61f76dedc6 | |||
| 06737f45ad | |||
| 65e8765bdd | |||
| c6a0212384 | |||
| e03614d91b | |||
| b82770d0a8 | |||
| 55e1326164 | |||
| b0aff68c8b | |||
| 6a99855c8c | |||
| 665aa6eb23 | |||
| 42caacbaf9 | |||
| 3531256c3f | |||
| 9a0db72eb4 | |||
| e11a42cf68 | |||
| 114769c2d9 | |||
| 9594596b8a | |||
| 69cf697aa3 | |||
| 45dbe5cb77 | |||
| a1ff35f6ce | |||
| 077a6949e2 | |||
| 44022f07ca | |||
| 30c1e1e86a | |||
| 9a90813877 | |||
| 1113218c6c | |||
| 2556c80250 | |||
| 8f8a5c639b | |||
| 9e9c37c1e8 | |||
| 6cbdbcb1f1 | |||
| c8835bf5db | |||
| 6dfedac7a7 | |||
| 83794eaf33 | |||
| bd1f43f9ee | |||
| 66ffe21ce2 | |||
| f2e86b7d30 | |||
| 5251e6787d | |||
| 856aee0a72 | |||
| 6b4c71f966 | |||
| dd6d040da5 | |||
| 203b60383f | |||
| 61ced0b221 | |||
| ae7675fee0 | |||
| 66ed26fbf9 | |||
| 98662c2a77 | |||
| 7099358985 | |||
| 9a706b3e3e | |||
| 71c9b03779 | |||
| dc7b9315b5 | |||
| 6c17b141db | |||
| 5d2cca855e | |||
| 61e10be04d | |||
| 20d5587851 | |||
| d8eccf03f1 | |||
| 6e40b58dc5 | |||
| 30dd8bcf2b | |||
| f0a11be0b8 | |||
| b8882fa00e | |||
| af337b7018 | |||
| f60267d208 | |||
| a0c844f4f6 | |||
| 7b84b92e72 | |||
| ce338c632d | |||
| d9f70c16f7 | |||
| d0299de898 | |||
| 9380c9ec81 | |||
| 941582ac2a | |||
| 04560b4475 | |||
| 0b30ad0da2 | |||
| cb6ea2c6fb | |||
| 89a5bbb10e | |||
| 2f59bb74cd | |||
| 6c6a3649ea | |||
| 05b97db747 | |||
| 543e4c0666 | |||
| e28619f769 | |||
| 4d8c2d3f4e | |||
| f53eeb8b33 | |||
| aba6d9b338 | |||
| cd5bef414c | |||
| 4f2d2ae4b8 | |||
| 1bd0ab7389 | |||
| 8799276c6e | |||
| 672aabf4ac | |||
| 796d6909d5 | |||
| a3dea99bbb | |||
| fc351a1896 | |||
| d9164281ab | |||
| cbb5b6e846 | |||
| 08bd39dbba | |||
| 430808e180 | |||
| 6976dc2b26 | |||
| 27063d5bae | |||
| 5be86b9dbb | |||
| afc78524fc | |||
| eb33a2451f | |||
| 891a0a0965 | |||
| 50f0797850 | |||
| 36cdf0e0be | |||
| d9cc3c3ec7 | |||
| 069a1608de | |||
| 60accfd601 | |||
| b1f2051b43 | |||
| 233e4af7f8 | |||
| dc1b808a28 | |||
| 91a423e60e | |||
| bd03a6d206 | |||
| d87da78eb5 | |||
| f3e82c2c80 | |||
| 569f05a99e | |||
| ece7c22df9 | |||
| 4eefd39172 | |||
| daae5d6859 | |||
| df76769a29 | |||
| fe72639925 | |||
| c3e6e1144f | |||
| cacb5d62dc | |||
| a8b47a55bc | |||
| 3159fdec9f | |||
| ea990a5381 | |||
| 134183ef16 | |||
| 67ab2536bc | |||
| 756a2ac25c | |||
| acaceb4103 | |||
| 7e3d66ec53 | |||
| 1ca9bb5aa8 | |||
| c641b733e1 | |||
| 16cf6bc852 | |||
| c51b7d7104 | |||
| 5c0ca92fd7 | |||
| 241e9bc253 | |||
| c8820adb56 | |||
| 0f4c6dd5b0 | |||
| f8ab9f62f6 | |||
| 217ed03b8e | |||
| 77e6058e4c | |||
| 4a60026162 | |||
| 3621292a0e | |||
| 6c296ccf8e | |||
| 6df1c36011 | |||
| 924da00f3e | |||
| 44dae22a3c | |||
| d35e251d6e | |||
| e19d2d6ec9 | |||
| 871255f28c | |||
| 9044aa4ed9 | |||
| 60c7efae3c | |||
| 48fc6ca60e | |||
| 7ac315e1eb | |||
| 374c6845d6 | |||
| c5cbe37007 | |||
| a2346e4666 | |||
| 2479ccc4c6 | |||
| 64dd8f5d65 | |||
| 47420a802a | |||
| 5cdb2b7163 | |||
| d4c080c7e4 | |||
| 065a47a446 | |||
| 5bd9ecb8df | |||
| 1cdec61be6 | |||
| b0ddb26e73 | |||
| 181bafd012 | |||
| e054fc1ef1 | |||
| 9d9ad86dd5 | |||
| afe4e5d62e | |||
| 52950f1322 | |||
| 026c80992e | |||
| 0ee2b74ff3 | |||
| 3a0f7eca54 | |||
| f4d530b4b1 | |||
| 4ccbfb56a4 | |||
| d02904c9a3 | |||
| c8279c0b99 | |||
| f4f184e115 | |||
| b2a86e312b | |||
| 9d56617caf | |||
| de7b8940fe | |||
| 09e94ec176 | |||
| 832ceeba56 | |||
| ea7c3c8485 | |||
| bc36c8074e | |||
| 9fccafa3ac | |||
| fa083098fc | |||
| 7688c437c0 | |||
| 697ac83040 | |||
| a742105c21 | |||
| 7a76ec9e02 | |||
| b2a0e7958b | |||
| 99439f0a5c | |||
| ef91c8123e | |||
| 5eb5742b3d | |||
| 296cf3e34b | |||
| e98c3f92c1 | |||
| d202dfc225 | |||
| 6202f6157a | |||
| b1e8e5389b | |||
| 95f6381da4 | |||
| b07e3b4a91 | |||
| 86bd9a2674 | |||
| 29a36839aa | |||
| 85cb7c92e7 | |||
| e827bc9a07 | |||
| a6f19a1657 | |||
| 6229d0c616 | |||
| bc6c969f21 | |||
| 8f4ede7785 | |||
| 877adb082c | |||
| 90818bb147 | |||
| f767a94c84 | |||
| 89e50b94d3 | |||
| c4d97d095f | |||
| 67fb3f10d5 | |||
| ea8d390596 | |||
| cff382605c | |||
| 52af8afac2 | |||
| 03b0268dc2 | |||
| c09e93e288 | |||
| 694e3b7f3a | |||
| 32c367090b | |||
| abcfe2b757 | |||
| f7687008b7 | |||
| b156264684 | |||
| 3f9a80942e | |||
| dc62e393c3 | |||
| 46be0f6610 | |||
| dd0a16c3d5 | |||
| a15ed6eaee | |||
| 3005565bba | |||
| cf45e7536f | |||
| 1d97d95c10 | |||
| 4a1b1675cb | |||
| 8c5249ba4b | |||
| b936591240 | |||
| 76e664d647 | |||
| 0253c2a756 | |||
| d27613f55c | |||
| ca8d478e87 | |||
| c63c17d49f | |||
| 801e58d52e | |||
| 06e9625c64 | |||
| 5800e8d8e9 | |||
| 623aa58163 | |||
| 45cfec5b29 | |||
| 5a9a231359 | |||
| 1736bf5510 | |||
| ee8931f886 | |||
| 1a1b891309 | |||
| 2eaac3d381 | |||
| f03249898a | |||
| 0981cfa902 | |||
| 37fbcfa22b | |||
| 0ee441a976 | |||
| cf8de3baa9 | |||
| 404ee238a3 | |||
| 5a5d171ba2 | |||
| aadee068b3 | |||
| a46e2ebfd8 | |||
| f710b1aac3 | |||
| f6fe6e70b9 | |||
| bed8861179 | |||
| 180d7b1b5b | |||
| 386416ee5d | |||
| 6b5aa91f3d | |||
| e80b80f5d1 | |||
| 9e35441281 | |||
| e28ad50bec | |||
| f48c5ee252 | |||
| 98a94dec29 | |||
| 7d95e7765d | |||
| ee75b30683 | |||
| ca9d4e3155 | |||
| 633bcbb6c4 | |||
| 2d4af61e6c | |||
| 45329912e6 | |||
| b9d56a8ecc | |||
| 91c1e53e52 | |||
| 73a87a8ea8 | |||
| bb0a614c39 | |||
| f11ea79406 | |||
| e817b20840 | |||
| 516f766a44 | |||
| f5791c79a5 | |||
| f6a1a76095 | |||
| bbb9145744 | |||
| 194853d860 | |||
| 92670d5711 | |||
| 8a2ea971e1 | |||
| 8d924b60d7 | |||
| 34595c266d | |||
| 638ae9bdd5 | |||
| 713ce7836f | |||
| 093c6652a8 | |||
| 17f0ac1eae | |||
| 43616d1874 | |||
| 9dc4f2ca80 | |||
| 73e3ac7dd8 | |||
| 8ff639913d | |||
| 45419586fe | |||
| d8a480b2a8 | |||
| 29d87246a2 | |||
| 58e638d3cb | |||
| b52380f376 | |||
| 4ae74fb7f6 | |||
| 7d1acd3d79 | |||
| 12e107a71b | |||
| fba72e1e8d | |||
| 7bbee053c6 | |||
| 6ea1a3bacf | |||
| 603afe4466 | |||
| 037ee8c07a | |||
| df1cef59d5 | |||
| 3fcd196c04 | |||
| 8ee5e7cd0a | |||
| 1ec85063ee | |||
| 92ba889cae | |||
| f17162c2e2 | |||
| fb233c0aa4 | |||
| 369c819a27 | |||
| f1eb4bd3a5 | |||
| 2f828683da | |||
| 13db151297 | |||
| bb95c231e5 | |||
| dcea14fb99 | |||
| 282fed27da | |||
| cf3ffe9c74 | |||
| 5d01a06245 | |||
| 02cdda56e2 | |||
| ffecd97665 | |||
| 779cf9418e | |||
| 34b4452645 | |||
| da1c4c23e6 | |||
| a5d0a21757 | |||
| 29454f7288 | |||
| e271711c5b | |||
| 4c78da3bbf | |||
| 71bab2c315 | |||
| fceba13b03 | |||
| 8ac3937bf4 | |||
| 1c1729854e | |||
| 14c78d9065 | |||
| b1cb9259da | |||
| 7d2af61989 | |||
| 03b5c2e246 | |||
| 33d5d5e24f | |||
| 3df2a4a70b | |||
| 6b41970e97 | |||
| 92eb6eb1b6 | |||
| 206238e83f | |||
| df882bbcbc | |||
| 6c1c3a99dd | |||
| 54067ec449 | |||
| 4c11e97922 | |||
| 8df9007a8e | |||
| 702b944698 | |||
| 172d24fd3c | |||
| 28b450fd3c | |||
| 485caf1d92 | |||
| 29cd75a6d2 | |||
| b3fe10baa8 | |||
| 093cc9faf0 | |||
| be4e809254 | |||
| dc5e15f919 | |||
| ad7b291062 | |||
| b54c1caa74 | |||
| c3cf123189 | |||
| 3a2900621c | |||
| 639cbf6d53 | |||
| e03b5754a8 | |||
| 4ce86a061f | |||
| fa6e170feb | |||
| 51f72daba1 | |||
| a130033480 | |||
| ef95ede833 | |||
| d06e5f25b0 | |||
| 2777ac96cc | |||
| fd42f1ef24 | |||
| 8b3ff5a82d | |||
| 482ebfbb68 | |||
| 67c4fa2966 | |||
| a3389a31cd | |||
| 8d74a976a1 | |||
| 6d104251b3 | |||
| f16c79bb9a | |||
| 1fe22e4b7b | |||
| c7fa2c04ad | |||
| 8ca882d1c8 | |||
| 5d368990dc | |||
| 4adbd7af4c | |||
| 1935a4aca3 | |||
| c4d96f6ea3 | |||
| 986d5641f6 | |||
| e163d5cfc7 | |||
| b1e7c772ae | |||
| dce1854ac4 | |||
| c4b4923ff8 | |||
| c20d10d4f2 | |||
| b0479d543d | |||
| 81704c1d40 | |||
| d3798bf251 | |||
| 4bb7c1701f | |||
| 5fd0f56258 | |||
| 37d7e89e93 | |||
| 3ab197075a | |||
| 12e8ac8b41 | |||
| 6783dc1312 | |||
| b489c71fa2 | |||
| cf5f6f9b13 | |||
| 860432acc5 | |||
| c9f7847fb3 | |||
| 6fad085a7d | |||
| 4b23ef4021 | |||
| bb96a190fd | |||
| e1eb457f3d | |||
| 51025aad57 | |||
| 14c4765be2 | |||
| 3afe996755 | |||
| 0891bd747a | |||
| f2693ee957 | |||
| 0327e71f0f | |||
| 69c2cf2c4f | |||
| 9f02be0823 | |||
| b5553af8ed | |||
| 4d6f4303f5 | |||
| 34f1ea1c0e | |||
| e3561ad38e | |||
| a7ccf0efff | |||
| f422c2ecad | |||
| db9c435ae0 | |||
| a53f89cd2c | |||
| 280c03dcad | |||
| e70fb42f87 | |||
| f633dbba64 | |||
| cc0f2d7074 | |||
| a820f248c8 | |||
| 6a6272ace3 | |||
| bcb747f886 | |||
| 771c85e347 | |||
| e5c358a1fe | |||
| 52c906f6b8 | |||
| ca1555d962 | |||
| 0d4f13219b | |||
| 7fdbbc846e | |||
| dbbbb103a0 | |||
| 2182ea1ce8 | |||
| f2cc9ec1dd | |||
| 54b24434e1 | |||
| 653ad562a4 | |||
| 7743b03129 | |||
| 84a601f364 | |||
| 88d131666c | |||
| d691f3b315 | |||
| 00a9d5f33e | |||
| eb0fd2f519 | |||
| 81efaa7481 | |||
| 2539c9e697 | |||
| 3dfd471fa4 | |||
| 4119526889 | |||
| 6b3346d90c | |||
| 312ce51de6 | |||
| 09914f508f | |||
| 45eda0f611 | |||
| de088d452f | |||
| 2f18430ce4 | |||
| 8d67e02d63 | |||
| 1b85eea28e | |||
| fb9a5f928f | |||
| 4459483862 | |||
| a0cf7ecc98 | |||
| 8e35a56386 | |||
| 30f738646e | |||
| 55281313d8 | |||
| 786799225c | |||
| c137fafa97 | |||
| cb22a3d556 | |||
| c7accb4599 | |||
| 72c85f93b6 | |||
| c1d5b8713b | |||
| 8310b91e00 | |||
| 71b5bf2eef | |||
| ab8b40745e | |||
| 16ec47573b | |||
| 556d0b44a3 | |||
| 0734d5b0b6 | |||
| f158a369a4 | |||
| bdbfb0f2a1 | |||
| e5653eaa93 | |||
| 3c4098038d | |||
| 8841e21dc9 | |||
| f5e03b264f | |||
| eb09a99eb0 | |||
| dc418a7033 | |||
| 15cc4345ab | |||
| 5272824d85 | |||
| 9bce0f2ff7 | |||
| d2e7e11dca | |||
| 6823aabf92 | |||
| f2dddc1226 | |||
| 957becabb9 | |||
| 7df03722ee | |||
| 4642f50d6b | |||
| 2decc3d6d3 | |||
| 2adc4ffa96 | |||
| c8fbf7640c | |||
| 46779ca865 | |||
| 86661e79d1 | |||
| b2a5d86e30 | |||
| d7f0ee49b7 | |||
| 5b86ee7291 | |||
| ad2ba252ee | |||
| 17ef20ea92 | |||
| 8c327e6523 | |||
| 386b2839e8 | |||
| 934593e0b6 | |||
| a7aa178f24 | |||
| 69122034e7 | |||
| 1117f4289d | |||
| 97bc4a092f | |||
| d942b8f1fb | |||
| 49dc9767b6 | |||
| 482965197d | |||
| 410b547f3c | |||
| f769e8247f | |||
| 2b4a536f85 | |||
| 92ae069629 | |||
| 6f40b21986 | |||
| 3084521521 | |||
| 4f12c86e74 | |||
| 204de99a64 | |||
| fd929f5dd9 | |||
| 7e9c8ba290 | |||
| 6f639f7bf0 | |||
| 3594ed67d1 | |||
| d36a06d8e1 | |||
| c816b960b5 | |||
| 5b02a43957 | |||
| 4913e56086 | |||
| 4d00bb98d1 | |||
| db2baae758 | |||
| fdecdf4b15 | |||
| 5c1d4aff23 | |||
| bf0edcb92e | |||
| 39fa8ef3c0 | |||
| 9e8a369bc8 | |||
| 3f3fe8935f | |||
| 82387630c7 | |||
| 16c5033514 | |||
| 46ffaee1e4 | |||
| d936f92a7d | |||
| b424ddf42d | |||
| b3d5a893fc | |||
| 69ea6eebae | |||
| 0892c34125 | |||
| 52e14d501f | |||
| 4d093160fc | |||
| 0bcca99573 | |||
| 63516c4a4f | |||
| 19fb79ffff | |||
| 02835de13d | |||
| 55b004d53d | |||
| c1b72a8ce6 | |||
| fa0bea87e6 | |||
| c94a7613ca | |||
| d146426dd8 | |||
| 1e1782c232 | |||
| dab5874fd7 | |||
| 4850227c04 | |||
| eb9a654cc3 | |||
| 4224bc0c43 | |||
| f893b23129 | |||
| 8c65880504 | |||
| 53cadf80fa | |||
| e177993bcc | |||
| 6a7f3ecc2e | |||
| 39cc99c89b | |||
| 25480293dc | |||
| 8b3bfc6bc9 | |||
| 19cff25300 | |||
| 848e1fe1f6 | |||
| fe147adec3 | |||
| 103809b65f | |||
| a398496dd4 | |||
| 839db8ef44 | |||
| bfd0530597 | |||
| 494ec5cd9c | |||
| fc61a4b88d | |||
| 50d8b02f8b | |||
| 860764a436 | |||
| 52d6a8990a | |||
| 87de67e4a9 | |||
| 8356b57fb4 | |||
| 3f04afee5c | |||
| 2117f61e8c | |||
| d40604b574 | |||
| 76129e9011 | |||
| 9c8411c7ff | |||
| c661d732b3 | |||
| fbe9daace6 | |||
| 651001bf6e | |||
| 9167f8a3ba | |||
| 6dc9ccffcd | |||
| 4b4e3badb7 | |||
| fe4dd23d39 | |||
| de6d71cc3b | |||
| 9e44052709 | |||
| 2d112f227a | |||
| bd8737d986 | |||
| 4b6d236eb7 | |||
| bf058bd5c6 | |||
| dfaf01e8aa | |||
| 2888dd6fd8 | |||
| 2e92ee8eee | |||
| 14b6a75507 | |||
| 2484a9db2c | |||
| bfc30794c5 | |||
| 27bc7a847b | |||
| 2a71877bec | |||
| 30bd920497 | |||
| 1d5b48b88d | |||
| 4295bad12f | |||
| 3a2eeaea7a | |||
| 12418ae91b | |||
| 783a24eb68 | |||
| 3f5c5cbe82 | |||
| 2439758ef3 | |||
| ac4aa97103 | |||
| 0bc93c6a1e | |||
| 685f1cbfb8 | |||
| e2d1e6b0c5 | |||
| 56cb9a0f4e | |||
| c8c81a360c | |||
| bdd43b7134 | |||
| c50d5a678a | |||
| 96b3af7cbc | |||
| 9e7bbc968d | |||
| 5fc6771543 | |||
| 0d049a0be7 | |||
| 01c24ab4cd | |||
| 155f5f35cd | |||
| 7ad6caf30a | |||
| ac8aab0043 | |||
| 14ddf36d46 | |||
| 25f1167c9d | |||
| 420225c2d5 | |||
| 45f5eaac5b | |||
| 5229dd65ce | |||
| cfe39afc11 | |||
| 2aa3ce15bd | |||
| c9873da732 | |||
| 8dd71f99cc | |||
| ab45975883 | |||
| 7f38ca239e | |||
| c3b982e759 | |||
| e330e80c46 | |||
| f0836d4d3a | |||
| 1289920217 | |||
| a6a58094c9 | |||
| 424cbd3248 | |||
| e59b9627c7 | |||
| f080c0cdcd | |||
| 29bda2ef7d | |||
| e8d9701a26 | |||
| 1d64692fd6 | |||
| 6f195cb8ec | |||
| 4c02a63acc | |||
| 0fc9fc7516 | |||
| 4450351b75 | |||
| 9bb15aaf1b | |||
| 65dd729e19 | |||
| c21142605d | |||
| 86e274faa3 | |||
| 5e8c129c7f | |||
| ab3b5ca4ef | |||
| 60a5afd752 | |||
| 9d0ea857fe | |||
| f763aea4fc | |||
| e16c04250e | |||
| ad99aa460b | |||
| e47f64f62d | |||
| c6d9da1571 | |||
| ab561d1ce8 | |||
| f39ba0136c | |||
| df60045bfe | |||
| 5e122f780f | |||
| eefe377159 | |||
| 20920c262d | |||
| 870612be1c | |||
| 266424ff0e | |||
| a8d48b758e | |||
| 67a8e0b5c6 | |||
| 7b7d424962 | |||
| a4e959818a | |||
| c3a71cc182 | |||
| da03cfdbe5 | |||
| 2b137d76fa | |||
| 81b8c111ca | |||
| fce98b9ca4 | |||
| c0dcae16f7 | |||
| c604f08749 | |||
| da21424416 | |||
| b5c83721ad | |||
| 9b21fca1a0 | |||
| af94b07771 | |||
| 0d23d28a65 | |||
| 710370ac24 | |||
| ed0a441e4d | |||
| 24e87cc0bb | |||
| 460693c153 | |||
| f54a94bd4c | |||
| a19b86add0 | |||
| 570944a48b | |||
| 5829b02323 | |||
| 5567a1e9ac | |||
| fa5016713f | |||
| f28a82de71 | |||
| 7c2fae7b9d | |||
| 70934e54cf | |||
| f6ad275030 | |||
| 6666a78936 | |||
| bbb2cdcceb | |||
| 6b6e18695f | |||
| b63962e90b | |||
| 4434de6241 | |||
| a2bca0e358 | |||
| 6d572424ac | |||
| d371d14c1f | |||
| 72eda1e909 | |||
| 7dbf8a8a8e | |||
| 133fdd7a37 | |||
| 0849262243 | |||
| 17095feb33 | |||
| f42ae46338 | |||
| 37ebf1827f | |||
| e65252725a | |||
| 6f53f2ac64 | |||
| e2679852ce | |||
| deaba46e1c | |||
| 989dab6259 | |||
| adacdc038d | |||
| f0aefaac42 | |||
| 1aeaa0094a | |||
| 6d3fa12f37 | |||
| 052f1eedd0 | |||
| 858da800be | |||
| 954cac3af7 | |||
| d0f171ebc6 | |||
| 90cf612ac7 | |||
| 802b5863ab | |||
| 4baa949a99 | |||
| 3bed04a6d3 | |||
| d548b800d5 | |||
| f7f199d929 | |||
| 5519fddb78 | |||
| a9ed748fb2 | |||
| dcba2bfd25 | |||
| 72c91ead8b | |||
| 774d0aa90c | |||
| 2eea67ce34 | |||
| db1c44f921 | |||
| e11287ec25 | |||
| 4f10adfb76 | |||
| f22803c59f | |||
| a72d4e5dc1 | |||
| 08f9aae8ae | |||
| 43c32fa1bf | |||
| 5afe024644 | |||
| c01bdb42fc | |||
| e3ef8d295f | |||
| ce1d677cdc | |||
| df5cacf8a2 | |||
| bb2c73348d | |||
| 4327653d70 | |||
| 5f7f4c9b91 | |||
| d44202e55b | |||
| df95447ea4 | |||
| 01852c7188 | |||
| 79c5697042 | |||
| 65e21faa3e | |||
| 658ba092e2 | |||
| b221d99e7b | |||
| b7af049589 | |||
| c2d863da99 | |||
| 6f9ba6ede4 | |||
| df4e6a0023 | |||
| d60fa65f85 | |||
| 8081a82fe4 | |||
| f42e5d5292 | |||
| 5a3f5b03d0 | |||
| 721902c2d4 | |||
| a450530c74 | |||
| 2b4886f37f | |||
| b45de3e17f | |||
| b2eea3e5a5 | |||
| f411c0fdd8 | |||
| 74d8431d01 | |||
| 3ea0cd75a5 | |||
| 5f6c746d25 | |||
| 1f2d30ebf4 | |||
| e6b366020a | |||
| 6dd6b45829 | |||
| e5800a2dac | |||
| 0d3d172108 | |||
| 86677b5f13 | |||
| 3f5b94f8ad | |||
| cf8cb8521b | |||
| ccd00caa70 | |||
| 57010b4c23 | |||
| 545a185614 | |||
| 1572e339f9 | |||
| 7782e5cc93 | |||
| bcdda551b3 | |||
| bc66c0f223 | |||
| 1b8c7ff4ec | |||
| 3bb81d1e4d | |||
| 756c44fcba | |||
| befa4428d0 | |||
| 60c678680a | |||
| 8bc9688d71 | |||
| aa8af2220c | |||
| b124b9af4d | |||
| ae403da8c1 | |||
| b5b8777c94 | |||
| 850f85ff59 | |||
| 84cc88831d | |||
| f4f9b165a7 | |||
| 3222d4c8df | |||
| 3173ead2e7 | |||
| 040f826c52 | |||
| 89d733d442 | |||
| df49e8350f | |||
| 3ced85080a | |||
| 0611ab9b4c | |||
| f450cafe3e | |||
| 1f29eb1875 | |||
| a4e5ae0938 | |||
| 77dacfcc30 | |||
| 0d9b6eaf71 | |||
| 7060ffaf34 | |||
| 02a37e2f89 | |||
| 9c1b1bc2b5 | |||
| b34156ca25 | |||
| 61bdb57b5d | |||
| 9df84e235c | |||
| 566ba4783e | |||
| b41b4b1732 | |||
| ccf9457c45 | |||
| 53aabdab66 | |||
| 8ff85c952e | |||
| afe1cb8234 | |||
| bd42505799 | |||
| 6c735c97c6 | |||
| 31a57cdf14 | |||
| 7ebbef25e7 | |||
| f836342194 | |||
| 5cf1a6c300 | |||
| bd506820b7 | |||
| 5815607924 | |||
| 9b40c9788f | |||
| 67b5e9093e | |||
| 57d1c036ec | |||
| 71722b753d | |||
| a2625c889a | |||
| c98b9da612 | |||
| 675717ff82 | |||
| 83ef7c6fe8 | |||
| 5f4c964309 | |||
| 66ba96d531 | |||
| d67b2da064 | |||
| e45fd4088f | |||
| 7e4a0eedf0 | |||
| 3f812f696d | |||
| 633249b08a | |||
| 21c3b1fbd2 | |||
| e9e6f925bf | |||
| 828b84084d | |||
| a6a0bfacc2 | |||
| c4b7e77498 | |||
| 91c7180bfd | |||
| b368acf941 | |||
| 7c39f516b9 | |||
| ce1ddcfcee | |||
| 945e8b402f | |||
| 5ed2bd0fb7 | |||
| bc908b854d | |||
| 2067b1138a | |||
| 1ffbdee156 | |||
| bd2812cac1 | |||
| f2a5eac256 | |||
| b4e647dbd1 | |||
| 530291f81c | |||
| de18e449a6 | |||
| dce19e0bea | |||
| 1f586d3102 | |||
| e5d01170d2 | |||
| 393dc51167 | |||
| 984cc7a4f2 | |||
| 0f11963127 | |||
| d8378f2a10 | |||
| a0a5480c97 | |||
| 3391108551 | |||
| 52551dad0f | |||
| 321414f6e3 | |||
| 7787fe42c8 | |||
| 3b66912742 | |||
| 278a25c63b | |||
| 0d124bb5a1 | |||
| 417caae589 | |||
| 3d306aacc5 | |||
| ea4ecaea03 | |||
| 6c90f9e395 | |||
| ddf81ba135 | |||
| 8ebb41caa6 | |||
| faf48b1684 | |||
| b8232d205b | |||
| 62745923cf | |||
| 090466123f | |||
| 38a3e36cd6 | |||
| e8dc634a40 | |||
| 0d0984a400 | |||
| 8640cad033 | |||
| dc29717623 | |||
| 814914924f | |||
| c7083488b2 | |||
| 4b4d383509 | |||
| b9986033cc | |||
| 3680e04817 | |||
| 21e23baa37 | |||
| fcd130ae15 | |||
| 8b52d5da85 | |||
| d1dffb84dc | |||
| 541350916d | |||
| 01afa9a749 | |||
| 57f5d4a570 | |||
| 4588393b76 | |||
| 0fd99d410e | |||
| 002fd4ce30 | |||
| 7b4ecb275f | |||
| 2df5d3a8ff | |||
| 7070bad53b | |||
| da62d6af26 | |||
| d0d4d14787 | |||
| 09d69b214b | |||
| 0e2aaebda4 | |||
| ec2c58163f | |||
| a28bee86ba | |||
| fb64892971 | |||
| 95ff692b14 | |||
| 8003615b1f | |||
| 948dc3c974 | |||
| 1afb724606 | |||
| 451281d833 | |||
| 485f11c945 | |||
| dbc79655b0 | |||
| 02f6aa6161 | |||
| 07c5264b41 | |||
| 7c178a6a78 | |||
| f56d53d7c1 | |||
| 4cd4a936d8 | |||
| 7bae4c39c6 | |||
| d55d95bbea | |||
| 5e48d56561 | |||
| 6a5098fb0c | |||
| 4e835e1772 | |||
| cce8cb4f5e | |||
| 8aed26aab1 | |||
| 01d5d4c2c8 | |||
| 592385cb07 | |||
| 85123b3e66 | |||
| 0fcf223960 | |||
| bf0bd06f20 | |||
| f07b0b6bd7 | |||
| 717b26c834 | |||
| 8bb8eab69b | |||
| 693d1c9452 | |||
| b049bb1d5c | |||
| c5c6b3bbc6 | |||
| 1df56a7cab | |||
| 3f5cc2507d | |||
| 5a85424295 | |||
| a53a8cca74 | |||
| 3fdee881f9 | |||
| a289dfaf88 | |||
| 8abd359b5b | |||
| 9359809b4f | |||
| cde5502f94 | |||
| 04e0a9d4a5 | |||
| 28ec0b8ebb | |||
| 37dfecf098 | |||
| 9d8ce872a4 | |||
| 07880dfe50 | |||
| 7eed9f8542 | |||
| a2e70dd6b2 | |||
| b9aeded957 | |||
| 027361f079 | |||
| ff10d1540f | |||
| 0f63fa23e0 | |||
| 22ef569e5e | |||
| f3663f0983 | |||
| 112ddaf55b | |||
| bda6fdf09c | |||
| a62198f33f | |||
| 4b0bfc52b4 | |||
| 78868813b1 | |||
| e8be178ac7 | |||
| 695428cd44 | |||
| 9ae779e442 | |||
| db92febdc7 | |||
| 5cf10cec34 | |||
| 7939c691f7 | |||
| ea2d54b0f7 | |||
| c66267a0f9 | |||
| f1d2f24534 | |||
| d83974e07f | |||
| f270f30728 | |||
| 55c237913c | |||
| 806671df7c | |||
| d64ee42ec3 | |||
| fe08f39900 | |||
| 5123ab57c9 | |||
| 313b327cd7 | |||
| 855d922a3e | |||
| cbe07ad23b | |||
| b3aba4ad99 | |||
| 21ad7f549d | |||
| 4b13fa45c5 | |||
| 485d40c752 | |||
| 8346ae8235 | |||
| 109c0f202a | |||
| 4231058aa1 | |||
| 6156d67e4a | |||
| 58bf036f52 | |||
| ff7d25c0f2 | |||
| 5f0b7f328c | |||
| 6559581bad | |||
| d78262f52b | |||
| bd566324ed | |||
| b65bf5082d | |||
| 939e4cba3e | |||
| 015a8763a0 | |||
| 02862d80eb | |||
| 7b0a3fc6d3 | |||
| b40b31b7b1 | |||
| 149d3d13d1 | |||
| 0f64d66cd8 | |||
| a85e2f7aad | |||
| 4f883b1264 | |||
| feb78d00cf | |||
| c9d54baa10 | |||
| 940f54dab1 | |||
| d83827a44e | |||
| 3a0a13d06d | |||
| 23f8e35716 | |||
| a251e61d73 | |||
| af06b1cd06 | |||
| 5b9120ba6c | |||
| 6c3a668400 | |||
| ad0f873ece | |||
| 3008a4ed7a | |||
| 95ef3a336b | |||
| 8ace30ee23 | |||
| eb0657c953 | |||
| 551354b1bb | |||
| 03b7891edc | |||
| 8978dff054 | |||
| d20844fefa | |||
| cd579a04dd | |||
| 15b8140bff | |||
| 9a93ad2e06 | |||
| bd4d3aa52b | |||
| bf32ab177f | |||
| 2ea883aa15 | |||
| 43cc296582 | |||
| 4c1aadd74e | |||
| 7d3719bf70 | |||
| c08164d864 | |||
| b156aa74a5 | |||
| ef52777ffb | |||
| b67ceab849 | |||
| 5ffade663a | |||
| 550f9e2afa | |||
| b6fa6cba22 | |||
| 6ee24a7527 | |||
| e2dcee1959 | |||
| 4fbea9512f | |||
| b7850ab839 | |||
| c0215baca5 | |||
| c62758c5b5 | |||
| 14358651e4 | |||
| 20dbacd22f | |||
| 8f2843bfcf | |||
| 9397372f87 | |||
| 8bbf6da052 | |||
| d67ff54f4b | |||
| 26728a85ad | |||
| c6d85a1b0b | |||
| 115e0fc119 | |||
| 1ceb703129 | |||
| fb28882f65 | |||
| d9c61fdb02 | |||
| 72c118a70f | |||
| 25241542d2 | |||
| 57a75e68b9 | |||
| dcf2168454 | |||
| c5e8d1c276 | |||
| 4093327b7f | |||
| d55358652b | |||
| f7d0cecdac | |||
| bcfa913450 | |||
| 43d8474caa | |||
| 8a2f3405d5 | |||
| 1248260df3 | |||
| 4cb804cf03 | |||
| 2b0dd8851c | |||
| 25db35e41e | |||
| 99000fada1 | |||
| 58b2f8ca17 | |||
| 8be3c1aaf2 | |||
| 2ee8639eaf | |||
| 32605578dd | |||
| fe0bba6df6 | |||
| 5fdcd6298f | |||
| 55943dbff6 | |||
| d12e571b20 | |||
| 0c15f05316 | |||
| 25c9f8e038 | |||
| a3811371cc | |||
| f734e196e5 | |||
| 6129f4722f | |||
| 585d7d0b87 | |||
| cdfc198f28 | |||
| 6fcb3d3d5e | |||
| 358d9ec06d | |||
| 322c8c1cf3 | |||
| 47eb0c34a2 | |||
| 4a290a85e6 | |||
| 5489c50cc0 | |||
| 066e40dada | |||
| 123d04ff7b | |||
| d5881736cf | |||
| 5e539da3da | |||
| ba58ca9d5c | |||
| 117007dfa1 | |||
| d29b3633d1 | |||
| 41e0275c95 | |||
| 7cf4baa92a | |||
| 6c3dfdfe6d | |||
| 149d159c05 | |||
| c0ad16f497 | |||
| 9edb631d52 | |||
| 58d2f0a41e | |||
| 255d9427b6 | |||
| d29f4489de | |||
| 4367fc54bf | |||
| b89116eb55 | |||
| 9430e9c8e2 | |||
| b01d53a247 | |||
| 65cbba3c2e | |||
| f93e7b91ff | |||
| 04069bab82 | |||
| 3106035ef9 | |||
| 18720b3302 | |||
| 12e546e63a | |||
| c28936fefb | |||
| 080d196138 | |||
| d3967b37cd | |||
| 0089ea2321 | |||
| 3f35124838 | |||
| 6ca5fb6b20 | |||
| a3b0273445 | |||
| 2a54797dce | |||
| 9770016eec | |||
| 6210716199 | |||
| e41a16dbf3 | |||
| 01f4aa018f | |||
| f9baeefbaf | |||
| af3417d6cc | |||
| 17bf8d0124 | |||
| c3e02286d3 | |||
| a9d82bf157 | |||
| e097df912e | |||
| 477bb6165f | |||
| 19850e8c5a | |||
| 12dcf76da9 | |||
| 36aac328e4 | |||
| 9cf81c7ad4 | |||
| 6c6417e595 | |||
| efa8ba5965 | |||
| fd02385c22 | |||
| 713b21de14 | |||
| af144a5184 | |||
| 9b31ae3146 | |||
| 4cb0012872 | |||
| eaa68327f7 | |||
| 68ef618028 | |||
| 3ecdafa685 | |||
| 20ae9dea19 | |||
| c9d46856a3 | |||
| 6d65f6646f | |||
| 34cd106357 | |||
| 714fce7e59 | |||
| 08e4ea384e | |||
| fe0f9743d3 | |||
| 57019e170f | |||
| 9f303cc116 | |||
| e504b20235 | |||
| f64b0d3818 | |||
| 1a26ea0911 | |||
| 7098ab6509 | |||
| 0d3589ca24 | |||
| f02ff62a08 | |||
| fbfc817c5f | |||
| 13601031cb | |||
| 442cad69a7 | |||
| be6545a366 | |||
| 32fdd36802 | |||
| fbc54526ed | |||
| a3306e4a81 | |||
| 3d858b21fa | |||
| 62b557f82c | |||
| 158c82ff5f | |||
| fd410c0281 | |||
| 65e3696029 | |||
| 690a5119f4 | |||
| cc0653c68a | |||
| 042a15d294 | |||
| 8e4c0f60a1 | |||
| 5615fc09e6 | |||
| d68f1e4cfa | |||
| 0c4901487d | |||
| 7f4b2d6e42 | |||
| 715a49d9fe | |||
| b98c1a0627 | |||
| da30292d84 | |||
| 7bda5c06de | |||
| 3d5847f4b3 | |||
| db400dffb5 | |||
| 199cdf6899 | |||
| 752171d5b8 | |||
| 7a5714cc85 | |||
| c77f5eee8c | |||
| aacfed40f8 | |||
| ec1059e74c | |||
| 3500217f94 | |||
| 427f8b1522 | |||
| 8b52bad16f | |||
| daed0b60bc | |||
| 4654f7aa37 | |||
| 70e87dad1c | |||
| ba8d8a6f05 | |||
| 605d267fe8 | |||
| 8f2a17585e | |||
| 51424d01a9 | |||
| f5ff9b2208 | |||
| 457f4c410a | |||
| bb013d5c3c | |||
| a9c7dbd17a | |||
| 09fdc946a0 | |||
| 31f1bce16b | |||
| 2f3ddaec20 | |||
| 7cd37e6e95 | |||
| a938009074 | |||
| 21d08ff742 | |||
| da8b41b12a | |||
| 6e031727fa | |||
| 381890b578 | |||
| 71fa6d765f | |||
| 9793130f6c | |||
| aadfa9aa9c | |||
| 645bba96cd |
@@ -3018,6 +3018,124 @@
|
|||||||
"contributions": [
|
"contributions": [
|
||||||
"code"
|
"code"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "koiakoia",
|
||||||
|
"name": "koiakoia",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/60405354?v=4",
|
||||||
|
"profile": "https://github.com/koiakoia",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "mustafa-online",
|
||||||
|
"name": "Mustafa Online",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/5323832?v=4",
|
||||||
|
"profile": "https://github.com/mustafa-online",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "franceslui",
|
||||||
|
"name": "franceslui",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/104601439?v=4",
|
||||||
|
"profile": "https://github.com/franceslui",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "Q4kK",
|
||||||
|
"name": "Q4kK",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/125313163?v=4",
|
||||||
|
"profile": "https://github.com/Q4kK",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "squintfox",
|
||||||
|
"name": "squintfox",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/55590532?v=4",
|
||||||
|
"profile": "https://github.com/squintfox",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "jeffclay",
|
||||||
|
"name": "Jeff Clay",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/1380084?v=4",
|
||||||
|
"profile": "https://github.com/jeffclay",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "PP-JN-RL",
|
||||||
|
"name": "Phil J R",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/52716446?v=4",
|
||||||
|
"profile": "https://github.com/PP-JN-RL",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "chandanchowdhury",
|
||||||
|
"name": "i_virus",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/1496725?v=4",
|
||||||
|
"profile": "https://www.corelight.com/",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "gitgrimbo",
|
||||||
|
"name": "Paul Grime",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/1020541?v=4",
|
||||||
|
"profile": "https://github.com/gitgrimbo",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "LeePorte",
|
||||||
|
"name": "Lee Porte",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/922815?v=4",
|
||||||
|
"profile": "https://leeporte.co.uk",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "bryanlopezinc",
|
||||||
|
"name": "BRYAN ",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/23613427?v=4",
|
||||||
|
"profile": "https://github.com/bryanlopezinc",
|
||||||
|
"contributions": [
|
||||||
|
"code",
|
||||||
|
"test"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "U-H-T",
|
||||||
|
"name": "U-H-T",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/64061710?v=4",
|
||||||
|
"profile": "https://github.com/U-H-T",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "Tyree",
|
||||||
|
"name": "Matt Tyree",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/5395363?v=4",
|
||||||
|
"profile": "https://github.com/Tyree",
|
||||||
|
"contributions": [
|
||||||
|
"doc"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
+166
@@ -0,0 +1,166 @@
|
|||||||
|
# --------------------------------------------
|
||||||
|
# REQUIRED: DB SETUP
|
||||||
|
# --------------------------------------------
|
||||||
|
MYSQL_DATABASE=snipeit
|
||||||
|
MYSQL_USER=snipeit
|
||||||
|
MYSQL_PASSWORD=changeme1234
|
||||||
|
MYSQL_ROOT_PASSWORD=changeme1234
|
||||||
|
# --------------------------------------------
|
||||||
|
# REQUIRED: BASIC APP SETTINGS
|
||||||
|
# --------------------------------------------
|
||||||
|
APP_ENV=develop
|
||||||
|
APP_DEBUG=false
|
||||||
|
# please regenerate the APP_KEY value by calling `docker-compose run --rm snipeit bash` and then `php artisan key:generate --show` and then copy paste the value here
|
||||||
|
APP_KEY=base64:3ilviXqB9u6DX1NRcyWGJ+sjySF+H18CPDGb3+IVwMQ=
|
||||||
|
APP_URL=http://localhost:8000
|
||||||
|
APP_TIMEZONE='UTC'
|
||||||
|
APP_LOCALE=en
|
||||||
|
MAX_RESULTS=500
|
||||||
|
|
||||||
|
# --------------------------------------------
|
||||||
|
# REQUIRED: UPLOADED FILE STORAGE SETTINGS
|
||||||
|
# --------------------------------------------
|
||||||
|
PRIVATE_FILESYSTEM_DISK=local
|
||||||
|
PUBLIC_FILESYSTEM_DISK=local_public
|
||||||
|
|
||||||
|
# --------------------------------------------
|
||||||
|
# REQUIRED: DATABASE SETTINGS
|
||||||
|
# --------------------------------------------
|
||||||
|
DB_CONNECTION=mysql
|
||||||
|
DB_HOST=mariadb
|
||||||
|
DB_DATABASE=snipeit
|
||||||
|
DB_USERNAME=snipeit
|
||||||
|
DB_PASSWORD=changeme1234
|
||||||
|
DB_PREFIX=null
|
||||||
|
DB_DUMP_PATH='/usr/bin'
|
||||||
|
DB_CHARSET=utf8mb4
|
||||||
|
DB_COLLATION=utf8mb4_unicode_ci
|
||||||
|
|
||||||
|
# --------------------------------------------
|
||||||
|
# OPTIONAL: SSL DATABASE SETTINGS
|
||||||
|
# --------------------------------------------
|
||||||
|
DB_SSL=false
|
||||||
|
DB_SSL_IS_PAAS=false
|
||||||
|
DB_SSL_KEY_PATH=null
|
||||||
|
DB_SSL_CERT_PATH=null
|
||||||
|
DB_SSL_CA_PATH=null
|
||||||
|
DB_SSL_CIPHER=null
|
||||||
|
DB_SSL_VERIFY_SERVER=null
|
||||||
|
|
||||||
|
# --------------------------------------------
|
||||||
|
# REQUIRED: OUTGOING MAIL SERVER SETTINGS
|
||||||
|
# --------------------------------------------
|
||||||
|
MAIL_DRIVER=smtp
|
||||||
|
MAIL_HOST=mailhog
|
||||||
|
MAIL_PORT=1025
|
||||||
|
MAIL_USERNAME=null
|
||||||
|
MAIL_PASSWORD=null
|
||||||
|
MAIL_ENCRYPTION=null
|
||||||
|
MAIL_FROM_ADDR=you@example.com
|
||||||
|
MAIL_FROM_NAME='Snipe-IT'
|
||||||
|
MAIL_REPLYTO_ADDR=you@example.com
|
||||||
|
MAIL_REPLYTO_NAME='Snipe-IT'
|
||||||
|
MAIL_AUTO_EMBED_METHOD='attachment'
|
||||||
|
|
||||||
|
# --------------------------------------------
|
||||||
|
# REQUIRED: IMAGE LIBRARY
|
||||||
|
# This should be gd or imagick
|
||||||
|
# --------------------------------------------
|
||||||
|
IMAGE_LIB=gd
|
||||||
|
|
||||||
|
|
||||||
|
# --------------------------------------------
|
||||||
|
# OPTIONAL: BACKUP SETTINGS
|
||||||
|
# --------------------------------------------
|
||||||
|
MAIL_BACKUP_NOTIFICATION_DRIVER=null
|
||||||
|
MAIL_BACKUP_NOTIFICATION_ADDRESS=null
|
||||||
|
BACKUP_ENV=true
|
||||||
|
|
||||||
|
|
||||||
|
# --------------------------------------------
|
||||||
|
# OPTIONAL: SESSION SETTINGS
|
||||||
|
# --------------------------------------------
|
||||||
|
SESSION_LIFETIME=12000
|
||||||
|
EXPIRE_ON_CLOSE=false
|
||||||
|
ENCRYPT=false
|
||||||
|
COOKIE_NAME=snipeit_session
|
||||||
|
COOKIE_DOMAIN=null
|
||||||
|
SECURE_COOKIES=false
|
||||||
|
API_TOKEN_EXPIRATION_YEARS=40
|
||||||
|
|
||||||
|
# --------------------------------------------
|
||||||
|
# OPTIONAL: SECURITY HEADER SETTINGS
|
||||||
|
# --------------------------------------------
|
||||||
|
APP_TRUSTED_PROXIES=192.168.1.1,10.0.0.1
|
||||||
|
ALLOW_IFRAMING=false
|
||||||
|
REFERRER_POLICY=same-origin
|
||||||
|
ENABLE_CSP=false
|
||||||
|
CORS_ALLOWED_ORIGINS=null
|
||||||
|
ENABLE_HSTS=false
|
||||||
|
|
||||||
|
# --------------------------------------------
|
||||||
|
# OPTIONAL: CACHE SETTINGS
|
||||||
|
# --------------------------------------------
|
||||||
|
CACHE_DRIVER=file
|
||||||
|
SESSION_DRIVER=file
|
||||||
|
QUEUE_DRIVER=sync
|
||||||
|
CACHE_PREFIX=snipeit
|
||||||
|
|
||||||
|
# --------------------------------------------
|
||||||
|
# OPTIONAL: REDIS SETTINGS
|
||||||
|
# --------------------------------------------
|
||||||
|
REDIS_HOST=redis
|
||||||
|
REDIS_PASSWORD=null
|
||||||
|
REDIS_PORT=6379
|
||||||
|
|
||||||
|
# --------------------------------------------
|
||||||
|
# OPTIONAL: MEMCACHED SETTINGS
|
||||||
|
# --------------------------------------------
|
||||||
|
MEMCACHED_HOST=null
|
||||||
|
MEMCACHED_PORT=null
|
||||||
|
|
||||||
|
# --------------------------------------------
|
||||||
|
# OPTIONAL: PUBLIC S3 Settings
|
||||||
|
# --------------------------------------------
|
||||||
|
PUBLIC_AWS_SECRET_ACCESS_KEY=null
|
||||||
|
PUBLIC_AWS_ACCESS_KEY_ID=null
|
||||||
|
PUBLIC_AWS_DEFAULT_REGION=null
|
||||||
|
PUBLIC_AWS_BUCKET=null
|
||||||
|
PUBLIC_AWS_URL=null
|
||||||
|
PUBLIC_AWS_BUCKET_ROOT=null
|
||||||
|
|
||||||
|
# --------------------------------------------
|
||||||
|
# OPTIONAL: PRIVATE S3 Settings
|
||||||
|
# --------------------------------------------
|
||||||
|
PRIVATE_AWS_ACCESS_KEY_ID=null
|
||||||
|
PRIVATE_AWS_SECRET_ACCESS_KEY=null
|
||||||
|
PRIVATE_AWS_DEFAULT_REGION=null
|
||||||
|
PRIVATE_AWS_BUCKET=null
|
||||||
|
PRIVATE_AWS_URL=null
|
||||||
|
PRIVATE_AWS_BUCKET_ROOT=null
|
||||||
|
|
||||||
|
# --------------------------------------------
|
||||||
|
# OPTIONAL: AWS Settings
|
||||||
|
# --------------------------------------------
|
||||||
|
AWS_ACCESS_KEY_ID=null
|
||||||
|
AWS_SECRET_ACCESS_KEY=null
|
||||||
|
AWS_DEFAULT_REGION=null
|
||||||
|
|
||||||
|
# --------------------------------------------
|
||||||
|
# OPTIONAL: LOGIN THROTTLING
|
||||||
|
# --------------------------------------------
|
||||||
|
LOGIN_MAX_ATTEMPTS=5
|
||||||
|
LOGIN_LOCKOUT_DURATION=60
|
||||||
|
RESET_PASSWORD_LINK_EXPIRES=900
|
||||||
|
|
||||||
|
# --------------------------------------------
|
||||||
|
# OPTIONAL: MISC
|
||||||
|
# --------------------------------------------
|
||||||
|
LOG_CHANNEL=stderr
|
||||||
|
LOG_MAX_DAYS=10
|
||||||
|
APP_LOCKED=false
|
||||||
|
APP_CIPHER=AES-256-CBC
|
||||||
|
APP_FORCE_TLS=false
|
||||||
|
GOOGLE_MAPS_API=
|
||||||
|
LDAP_MEM_LIM=500M
|
||||||
|
LDAP_TIME_LIM=600
|
||||||
+21
-14
@@ -1,18 +1,18 @@
|
|||||||
# --------------------------------------------
|
# --------------------------------------------
|
||||||
# REQUIRED: DB SETUP
|
# REQUIRED: DOCKER SPECIFIC SETTINGS
|
||||||
# --------------------------------------------
|
# --------------------------------------------
|
||||||
MYSQL_DATABASE=snipeit
|
APP_VERSION=v6.4.1
|
||||||
MYSQL_USER=snipeit
|
APP_PORT=8000
|
||||||
MYSQL_PASSWORD=changeme1234
|
|
||||||
MYSQL_ROOT_PASSWORD=changeme1234
|
|
||||||
# --------------------------------------------
|
# --------------------------------------------
|
||||||
# REQUIRED: BASIC APP SETTINGS
|
# REQUIRED: BASIC APP SETTINGS
|
||||||
# --------------------------------------------
|
# --------------------------------------------
|
||||||
APP_ENV=develop
|
APP_ENV=production
|
||||||
APP_DEBUG=false
|
APP_DEBUG=false
|
||||||
# please regenerate the APP_KEY value by calling `docker-compose run --rm snipeit bash` and then `php artisan key:generate --show` and then copy paste the value here
|
# Please regenerate the APP_KEY value by calling `docker compose run --rm snipeit php artisan key:generate --show`. Copy paste the value here
|
||||||
APP_KEY=base64:3ilviXqB9u6DX1NRcyWGJ+sjySF+H18CPDGb3+IVwMQ=
|
APP_KEY=base64:3ilviXqB9u6DX1NRcyWGJ+sjySF+H18CPDGb3+IVwMQ=
|
||||||
APP_URL=http://localhost:8000
|
APP_URL=http://localhost:8000
|
||||||
|
# https://en.wikipedia.org/wiki/List_of_tz_database_time_zones - TZ identifier
|
||||||
APP_TIMEZONE='UTC'
|
APP_TIMEZONE='UTC'
|
||||||
APP_LOCALE=en
|
APP_LOCALE=en
|
||||||
MAX_RESULTS=500
|
MAX_RESULTS=500
|
||||||
@@ -27,10 +27,12 @@ PUBLIC_FILESYSTEM_DISK=local_public
|
|||||||
# REQUIRED: DATABASE SETTINGS
|
# REQUIRED: DATABASE SETTINGS
|
||||||
# --------------------------------------------
|
# --------------------------------------------
|
||||||
DB_CONNECTION=mysql
|
DB_CONNECTION=mysql
|
||||||
DB_HOST=mariadb
|
DB_HOST=db
|
||||||
|
DB_PORT='3306'
|
||||||
DB_DATABASE=snipeit
|
DB_DATABASE=snipeit
|
||||||
DB_USERNAME=snipeit
|
DB_USERNAME=snipeit
|
||||||
DB_PASSWORD=changeme1234
|
DB_PASSWORD=changeme1234
|
||||||
|
MYSQL_ROOT_PASSWORD=changeme1234
|
||||||
DB_PREFIX=null
|
DB_PREFIX=null
|
||||||
DB_DUMP_PATH='/usr/bin'
|
DB_DUMP_PATH='/usr/bin'
|
||||||
DB_CHARSET=utf8mb4
|
DB_CHARSET=utf8mb4
|
||||||
@@ -45,29 +47,35 @@ DB_SSL_KEY_PATH=null
|
|||||||
DB_SSL_CERT_PATH=null
|
DB_SSL_CERT_PATH=null
|
||||||
DB_SSL_CA_PATH=null
|
DB_SSL_CA_PATH=null
|
||||||
DB_SSL_CIPHER=null
|
DB_SSL_CIPHER=null
|
||||||
|
DB_SSL_VERIFY_SERVER=null
|
||||||
|
|
||||||
# --------------------------------------------
|
# --------------------------------------------
|
||||||
# REQUIRED: OUTGOING MAIL SERVER SETTINGS
|
# REQUIRED: OUTGOING MAIL SERVER SETTINGS
|
||||||
# --------------------------------------------
|
# --------------------------------------------
|
||||||
MAIL_DRIVER=smtp
|
MAIL_MAILER=smtp
|
||||||
MAIL_HOST=mailhog
|
MAIL_HOST=mailhog
|
||||||
MAIL_PORT=1025
|
MAIL_PORT=1025
|
||||||
MAIL_USERNAME=null
|
MAIL_USERNAME=null
|
||||||
MAIL_PASSWORD=null
|
MAIL_PASSWORD=null
|
||||||
MAIL_ENCRYPTION=null
|
MAIL_TLS_VERIFY_PEER=true
|
||||||
MAIL_FROM_ADDR=you@example.com
|
MAIL_FROM_ADDR=you@example.com
|
||||||
MAIL_FROM_NAME='Snipe-IT'
|
MAIL_FROM_NAME='Snipe-IT'
|
||||||
MAIL_REPLYTO_ADDR=you@example.com
|
MAIL_REPLYTO_ADDR=you@example.com
|
||||||
MAIL_REPLYTO_NAME='Snipe-IT'
|
MAIL_REPLYTO_NAME='Snipe-IT'
|
||||||
MAIL_AUTO_EMBED_METHOD='attachment'
|
MAIL_AUTO_EMBED_METHOD='attachment'
|
||||||
|
|
||||||
|
# --------------------------------------------
|
||||||
|
# REQUIRED: DATA PROTECTION
|
||||||
|
# --------------------------------------------
|
||||||
|
ALLOW_BACKUP_DELETE=false
|
||||||
|
ALLOW_DATA_PURGE=false
|
||||||
|
|
||||||
# --------------------------------------------
|
# --------------------------------------------
|
||||||
# REQUIRED: IMAGE LIBRARY
|
# REQUIRED: IMAGE LIBRARY
|
||||||
# This should be gd or imagick
|
# This should be gd or imagick
|
||||||
# --------------------------------------------
|
# --------------------------------------------
|
||||||
IMAGE_LIB=gd
|
IMAGE_LIB=gd
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------
|
# --------------------------------------------
|
||||||
# OPTIONAL: BACKUP SETTINGS
|
# OPTIONAL: BACKUP SETTINGS
|
||||||
# --------------------------------------------
|
# --------------------------------------------
|
||||||
@@ -75,7 +83,6 @@ MAIL_BACKUP_NOTIFICATION_DRIVER=null
|
|||||||
MAIL_BACKUP_NOTIFICATION_ADDRESS=null
|
MAIL_BACKUP_NOTIFICATION_ADDRESS=null
|
||||||
BACKUP_ENV=true
|
BACKUP_ENV=true
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------
|
# --------------------------------------------
|
||||||
# OPTIONAL: SESSION SETTINGS
|
# OPTIONAL: SESSION SETTINGS
|
||||||
# --------------------------------------------
|
# --------------------------------------------
|
||||||
@@ -90,7 +97,7 @@ API_TOKEN_EXPIRATION_YEARS=40
|
|||||||
# --------------------------------------------
|
# --------------------------------------------
|
||||||
# OPTIONAL: SECURITY HEADER SETTINGS
|
# OPTIONAL: SECURITY HEADER SETTINGS
|
||||||
# --------------------------------------------
|
# --------------------------------------------
|
||||||
APP_TRUSTED_PROXIES=192.168.1.1,10.0.0.1
|
APP_TRUSTED_PROXIES=192.168.1.1,10.0.0.1,172.0.0.0/8
|
||||||
ALLOW_IFRAMING=false
|
ALLOW_IFRAMING=false
|
||||||
REFERRER_POLICY=same-origin
|
REFERRER_POLICY=same-origin
|
||||||
ENABLE_CSP=false
|
ENABLE_CSP=false
|
||||||
@@ -108,7 +115,7 @@ CACHE_PREFIX=snipeit
|
|||||||
# --------------------------------------------
|
# --------------------------------------------
|
||||||
# OPTIONAL: REDIS SETTINGS
|
# OPTIONAL: REDIS SETTINGS
|
||||||
# --------------------------------------------
|
# --------------------------------------------
|
||||||
REDIS_HOST=redis
|
REDIS_HOST=null
|
||||||
REDIS_PASSWORD=null
|
REDIS_PASSWORD=null
|
||||||
REDIS_PORT=6379
|
REDIS_PORT=6379
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -36,11 +36,12 @@ DB_SSL_KEY_PATH=null
|
|||||||
DB_SSL_CERT_PATH=null
|
DB_SSL_CERT_PATH=null
|
||||||
DB_SSL_CA_PATH=null
|
DB_SSL_CA_PATH=null
|
||||||
DB_SSL_CIPHER=null
|
DB_SSL_CIPHER=null
|
||||||
|
DB_SSL_VERIFY_SERVER=null
|
||||||
|
|
||||||
# --------------------------------------------
|
# --------------------------------------------
|
||||||
# REQUIRED: OUTGOING MAIL SERVER SETTINGS
|
# REQUIRED: OUTGOING MAIL SERVER SETTINGS
|
||||||
# --------------------------------------------
|
# --------------------------------------------
|
||||||
MAIL_DRIVER="log"
|
MAIL_MAILER="log"
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------
|
# --------------------------------------------
|
||||||
|
|||||||
+10
-3
@@ -42,21 +42,26 @@ DB_SSL_KEY_PATH=null
|
|||||||
DB_SSL_CERT_PATH=null
|
DB_SSL_CERT_PATH=null
|
||||||
DB_SSL_CA_PATH=null
|
DB_SSL_CA_PATH=null
|
||||||
DB_SSL_CIPHER=null
|
DB_SSL_CIPHER=null
|
||||||
|
DB_SSL_VERIFY_SERVER=null
|
||||||
|
|
||||||
# --------------------------------------------
|
# --------------------------------------------
|
||||||
# REQUIRED: OUTGOING MAIL SERVER SETTINGS
|
# REQUIRED: OUTGOING MAIL SERVER SETTINGS
|
||||||
# --------------------------------------------
|
# --------------------------------------------
|
||||||
MAIL_DRIVER=smtp
|
MAIL_MAILER=smtp
|
||||||
MAIL_HOST=email-smtp.us-west-2.amazonaws.com
|
MAIL_HOST=email-smtp.us-west-2.amazonaws.com
|
||||||
MAIL_PORT=587
|
MAIL_PORT=587
|
||||||
MAIL_USERNAME=YOURUSERNAME
|
MAIL_USERNAME=YOURUSERNAME
|
||||||
MAIL_PASSWORD=YOURPASSWORD
|
MAIL_PASSWORD=YOURPASSWORD
|
||||||
MAIL_ENCRYPTION=null
|
|
||||||
MAIL_FROM_ADDR=you@example.com
|
MAIL_FROM_ADDR=you@example.com
|
||||||
MAIL_FROM_NAME='Snipe-IT'
|
MAIL_FROM_NAME='Snipe-IT'
|
||||||
MAIL_REPLYTO_ADDR=you@example.com
|
MAIL_REPLYTO_ADDR=you@example.com
|
||||||
MAIL_REPLYTO_NAME='Snipe-IT'
|
MAIL_REPLYTO_NAME='Snipe-IT'
|
||||||
MAIL_AUTO_EMBED_METHOD='attachment'
|
MAIL_AUTO_EMBED_METHOD='attachment'
|
||||||
|
MAIL_TLS_VERIFY_PEER=true
|
||||||
|
|
||||||
|
# MAIL_ENCRYPTION is no longer supported. SymfonyMailer will use tls if it's
|
||||||
|
# advertised, and won't if it's not. If you want to use your mail server's IP but it's failing
|
||||||
|
# because of certificate errors, set MAIL_TLS_VERIFY_PEER-true
|
||||||
|
|
||||||
# --------------------------------------------
|
# --------------------------------------------
|
||||||
# REQUIRED: IMAGE LIBRARY
|
# REQUIRED: IMAGE LIBRARY
|
||||||
@@ -86,6 +91,7 @@ COOKIE_DOMAIN=null
|
|||||||
SECURE_COOKIES=false
|
SECURE_COOKIES=false
|
||||||
API_TOKEN_EXPIRATION_YEARS=15
|
API_TOKEN_EXPIRATION_YEARS=15
|
||||||
BS_TABLE_STORAGE=cookieStorage
|
BS_TABLE_STORAGE=cookieStorage
|
||||||
|
BS_TABLE_DEEPLINK=true
|
||||||
|
|
||||||
# --------------------------------------------
|
# --------------------------------------------
|
||||||
# OPTIONAL: SECURITY HEADER SETTINGS
|
# OPTIONAL: SECURITY HEADER SETTINGS
|
||||||
@@ -94,6 +100,7 @@ APP_TRUSTED_PROXIES=192.168.1.1,10.0.0.1
|
|||||||
ALLOW_IFRAMING=false
|
ALLOW_IFRAMING=false
|
||||||
REFERRER_POLICY=same-origin
|
REFERRER_POLICY=same-origin
|
||||||
ENABLE_CSP=false
|
ENABLE_CSP=false
|
||||||
|
ADDITIONAL_CSP_URLS=null
|
||||||
CORS_ALLOWED_ORIGINS=null
|
CORS_ALLOWED_ORIGINS=null
|
||||||
ENABLE_HSTS=false
|
ENABLE_HSTS=false
|
||||||
|
|
||||||
@@ -190,4 +197,4 @@ ARGON_TIME=2
|
|||||||
# OPTIONAL: SCIM
|
# OPTIONAL: SCIM
|
||||||
# --------------------------------------------
|
# --------------------------------------------
|
||||||
SCIM_TRACE=false
|
SCIM_TRACE=false
|
||||||
SCIM_STANDARDS_COMPLIANCE=false
|
SCIM_STANDARDS_COMPLIANCE=false
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@ DB_PASSWORD=null
|
|||||||
# --------------------------------------------
|
# --------------------------------------------
|
||||||
# REQUIRED: OUTGOING MAIL SERVER SETTINGS
|
# REQUIRED: OUTGOING MAIL SERVER SETTINGS
|
||||||
# --------------------------------------------
|
# --------------------------------------------
|
||||||
MAIL_DRIVER=log
|
MAIL_MAILER=log
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------
|
# --------------------------------------------
|
||||||
|
|||||||
+1
-1
@@ -18,6 +18,6 @@ APP_KEY=base64:tu9NRh/a6+dCXBDGvg0Gv/0TcABnFsbT4AKxrr8mwQo=
|
|||||||
LOGIN_MAX_ATTEMPTS=1000000
|
LOGIN_MAX_ATTEMPTS=1000000
|
||||||
LOGIN_LOCKOUT_DURATION=100000000
|
LOGIN_LOCKOUT_DURATION=100000000
|
||||||
|
|
||||||
MAIL_DRIVER=log
|
MAIL_MAILER=log
|
||||||
MAIL_FROM_ADDR=you@example.com
|
MAIL_FROM_ADDR=you@example.com
|
||||||
MAIL_FROM_NAME=Snipe-IT
|
MAIL_FROM_NAME=Snipe-IT
|
||||||
|
|||||||
+1
-1
@@ -15,6 +15,6 @@ APP_KEY=base64:tu9NRh/a6+dCXBDGvg0Gv/0TcABnFsbT4AKxrr8mwQo=
|
|||||||
LOGIN_MAX_ATTEMPTS=1000000
|
LOGIN_MAX_ATTEMPTS=1000000
|
||||||
LOGIN_LOCKOUT_DURATION=100000000
|
LOGIN_LOCKOUT_DURATION=100000000
|
||||||
|
|
||||||
MAIL_DRIVER=log
|
MAIL_MAILER=log
|
||||||
MAIL_FROM_ADDR=you@example.com
|
MAIL_FROM_ADDR=you@example.com
|
||||||
MAIL_FROM_NAME=Snipe-IT
|
MAIL_FROM_NAME=Snipe-IT
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ jobs:
|
|||||||
|
|
||||||
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
|
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
|
||||||
- name: Run Codacy Analysis CLI
|
- name: Run Codacy Analysis CLI
|
||||||
uses: codacy/codacy-analysis-cli-action@v4.4.0
|
uses: codacy/codacy-analysis-cli-action@v4.4.1
|
||||||
with:
|
with:
|
||||||
# Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository
|
# Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository
|
||||||
# You can also omit the token and run the tools that support default configurations
|
# You can also omit the token and run the tools that support default configurations
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Crowdin push
|
- name: Crowdin push
|
||||||
uses: crowdin/github-action@v1
|
uses: crowdin/github-action@v2
|
||||||
with:
|
with:
|
||||||
upload_sources: true
|
upload_sources: true
|
||||||
upload_translations: false
|
upload_translations: false
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ jobs:
|
|||||||
# https://github.com/docker/build-push-action
|
# https://github.com/docker/build-push-action
|
||||||
- name: Build and push 'snipe-it' image
|
- name: Build and push 'snipe-it' image
|
||||||
id: docker_build
|
id: docker_build
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: ./Dockerfile.alpine
|
file: ./Dockerfile.alpine
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ jobs:
|
|||||||
# https://github.com/docker/build-push-action
|
# https://github.com/docker/build-push-action
|
||||||
- name: Build and push 'snipe-it' image
|
- name: Build and push 'snipe-it' image
|
||||||
id: docker_build
|
id: docker_build
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: ./Dockerfile
|
file: ./Dockerfile
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
php-version:
|
php-version:
|
||||||
- "7.4"
|
- "8.1"
|
||||||
- "8.0"
|
- "8.2"
|
||||||
- "8.1.1"
|
- "8.3"
|
||||||
|
|
||||||
name: PHP ${{ matrix.php-version }}
|
name: PHP ${{ matrix.php-version }}
|
||||||
|
|
||||||
@@ -58,11 +58,17 @@ jobs:
|
|||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
|
run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
|
||||||
|
|
||||||
- name: Generate key
|
- name: Setup Laravel
|
||||||
run: php artisan key:generate
|
env:
|
||||||
|
DB_CONNECTION: mysql
|
||||||
- name: Directory Permissions
|
DB_DATABASE: snipeit
|
||||||
run: chmod -R 777 storage bootstrap/cache
|
DB_PORT: ${{ job.services.mysql.ports[3306] }}
|
||||||
|
DB_USERNAME: root
|
||||||
|
run: |
|
||||||
|
php artisan key:generate
|
||||||
|
php artisan migrate --force
|
||||||
|
php artisan passport:install
|
||||||
|
chmod -R 777 storage bootstrap/cache
|
||||||
|
|
||||||
- name: Execute tests (Unit and Feature tests) via PHPUnit
|
- name: Execute tests (Unit and Feature tests) via PHPUnit
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
name: Tests in Postgres
|
||||||
|
|
||||||
|
on: workflow_dispatch
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
tests:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
services:
|
||||||
|
postgresql:
|
||||||
|
image: postgres
|
||||||
|
env:
|
||||||
|
POSTGRES_DB: snipeit
|
||||||
|
POSTGRES_USER: snipeit
|
||||||
|
POSTGRES_PASSWORD: password
|
||||||
|
ports:
|
||||||
|
- 5432:5432
|
||||||
|
options: --health-cmd=pg_isready --health-interval=10s --health-timeout=5s --health-retries=3
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
php-version:
|
||||||
|
- "8.2"
|
||||||
|
|
||||||
|
name: PHP ${{ matrix.php-version }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: "${{ matrix.php-version }}"
|
||||||
|
coverage: none
|
||||||
|
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Get Composer Cache Directory
|
||||||
|
id: composer-cache
|
||||||
|
run: |
|
||||||
|
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
|
||||||
|
- uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: ${{ steps.composer-cache.outputs.dir }}
|
||||||
|
key: ${{ runner.os }}-${{ matrix.php-version }}-composer-${{ hashFiles('**/composer.lock') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-composer-
|
||||||
|
|
||||||
|
- name: Copy .env
|
||||||
|
run: |
|
||||||
|
cp -v .env.testing.example .env
|
||||||
|
cp -v .env.testing.example .env.testing
|
||||||
|
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
|
||||||
|
|
||||||
|
- name: Setup Laravel
|
||||||
|
env:
|
||||||
|
DB_CONNECTION: pgsql
|
||||||
|
DB_DATABASE: snipeit
|
||||||
|
DB_PORT: ${{ job.services.postgresql.ports[5432] }}
|
||||||
|
DB_USERNAME: snipeit
|
||||||
|
DB_PASSWORD: password
|
||||||
|
run: |
|
||||||
|
php artisan key:generate
|
||||||
|
php artisan migrate --force
|
||||||
|
php artisan passport:install
|
||||||
|
chmod -R 777 storage bootstrap/cache
|
||||||
|
|
||||||
|
- name: Execute tests (Unit and Feature tests) via PHPUnit
|
||||||
|
env:
|
||||||
|
DB_CONNECTION: pgsql
|
||||||
|
DB_DATABASE: snipeit
|
||||||
|
DB_PORT: ${{ job.services.postgresql.ports[5432] }}
|
||||||
|
DB_USERNAME: snipeit
|
||||||
|
DB_PASSWORD: password
|
||||||
|
run: php artisan test --parallel
|
||||||
@@ -49,6 +49,9 @@ jobs:
|
|||||||
- name: Generate key
|
- name: Generate key
|
||||||
run: php artisan key:generate
|
run: php artisan key:generate
|
||||||
|
|
||||||
|
- name: Setup Passport
|
||||||
|
run: php artisan passport:keys
|
||||||
|
|
||||||
- name: Directory Permissions
|
- name: Directory Permissions
|
||||||
run: chmod -R 777 storage bootstrap/cache
|
run: chmod -R 777 storage bootstrap/cache
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
"DOC2": "In other words, what you see locally are the requirements for your _current_ install",
|
"DOC2": "In other words, what you see locally are the requirements for your _current_ install",
|
||||||
"DOC3": "Please don't rely on these versions for planning upgrades unless you've fetched the most recent version",
|
"DOC3": "Please don't rely on these versions for planning upgrades unless you've fetched the most recent version",
|
||||||
"DOC4": "You should really just ignore it and run upgrade.php. Really",
|
"DOC4": "You should really just ignore it and run upgrade.php. Really",
|
||||||
"php_min_version": "7.4.0",
|
"php_min_version": "8.1.0",
|
||||||
"php_max_major_minor": "8.1",
|
"php_max_major_minor": "8.3",
|
||||||
"php_max_wontwork": "8.2.0",
|
"php_max_wontwork": "8.4.0",
|
||||||
"current_snipeit_version": "6.3"
|
"current_snipeit_version": "7.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -432,6 +432,23 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
|
|||||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bilias"><img src="https://avatars.githubusercontent.com/u/47315739?v=4?s=110" width="110px;" alt="bilias"/><br /><sub><b>bilias</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=bilias" title="Code">💻</a></td>
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bilias"><img src="https://avatars.githubusercontent.com/u/47315739?v=4?s=110" width="110px;" alt="bilias"/><br /><sub><b>bilias</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=bilias" title="Code">💻</a></td>
|
||||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/coach1988"><img src="https://avatars.githubusercontent.com/u/2565989?v=4?s=110" width="110px;" alt="coach1988"/><br /><sub><b>coach1988</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=coach1988" title="Code">💻</a></td>
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/coach1988"><img src="https://avatars.githubusercontent.com/u/2565989?v=4?s=110" width="110px;" alt="coach1988"/><br /><sub><b>coach1988</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=coach1988" title="Code">💻</a></td>
|
||||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mauro-miatello"><img src="https://avatars.githubusercontent.com/u/11910225?v=4?s=110" width="110px;" alt="MrM"/><br /><sub><b>MrM</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=mauro-miatello" title="Code">💻</a></td>
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mauro-miatello"><img src="https://avatars.githubusercontent.com/u/11910225?v=4?s=110" width="110px;" alt="MrM"/><br /><sub><b>MrM</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=mauro-miatello" title="Code">💻</a></td>
|
||||||
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/koiakoia"><img src="https://avatars.githubusercontent.com/u/60405354?v=4?s=110" width="110px;" alt="koiakoia"/><br /><sub><b>koiakoia</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=koiakoia" title="Code">💻</a></td>
|
||||||
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mustafa-online"><img src="https://avatars.githubusercontent.com/u/5323832?v=4?s=110" width="110px;" alt="Mustafa Online"/><br /><sub><b>Mustafa Online</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=mustafa-online" title="Code">💻</a></td>
|
||||||
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/franceslui"><img src="https://avatars.githubusercontent.com/u/104601439?v=4?s=110" width="110px;" alt="franceslui"/><br /><sub><b>franceslui</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=franceslui" title="Code">💻</a></td>
|
||||||
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Q4kK"><img src="https://avatars.githubusercontent.com/u/125313163?v=4?s=110" width="110px;" alt="Q4kK"/><br /><sub><b>Q4kK</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=Q4kK" title="Code">💻</a></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/squintfox"><img src="https://avatars.githubusercontent.com/u/55590532?v=4?s=110" width="110px;" alt="squintfox"/><br /><sub><b>squintfox</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=squintfox" title="Code">💻</a></td>
|
||||||
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jeffclay"><img src="https://avatars.githubusercontent.com/u/1380084?v=4?s=110" width="110px;" alt="Jeff Clay"/><br /><sub><b>Jeff Clay</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=jeffclay" title="Code">💻</a></td>
|
||||||
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/PP-JN-RL"><img src="https://avatars.githubusercontent.com/u/52716446?v=4?s=110" width="110px;" alt="Phil J R"/><br /><sub><b>Phil J R</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=PP-JN-RL" title="Code">💻</a></td>
|
||||||
|
<td align="center" valign="top" width="14.28%"><a href="https://www.corelight.com/"><img src="https://avatars.githubusercontent.com/u/1496725?v=4?s=110" width="110px;" alt="i_virus"/><br /><sub><b>i_virus</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=chandanchowdhury" title="Code">💻</a></td>
|
||||||
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/gitgrimbo"><img src="https://avatars.githubusercontent.com/u/1020541?v=4?s=110" width="110px;" alt="Paul Grime"/><br /><sub><b>Paul Grime</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=gitgrimbo" title="Code">💻</a></td>
|
||||||
|
<td align="center" valign="top" width="14.28%"><a href="https://leeporte.co.uk"><img src="https://avatars.githubusercontent.com/u/922815?v=4?s=110" width="110px;" alt="Lee Porte"/><br /><sub><b>Lee Porte</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=LeePorte" title="Code">💻</a></td>
|
||||||
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bryanlopezinc"><img src="https://avatars.githubusercontent.com/u/23613427?v=4?s=110" width="110px;" alt="BRYAN "/><br /><sub><b>BRYAN </b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=bryanlopezinc" title="Code">💻</a> <a href="https://github.com/snipe/snipe-it/commits?author=bryanlopezinc" title="Tests">⚠️</a></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/U-H-T"><img src="https://avatars.githubusercontent.com/u/64061710?v=4?s=110" width="110px;" alt="U-H-T"/><br /><sub><b>U-H-T</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=U-H-T" title="Code">💻</a></td>
|
||||||
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Tyree"><img src="https://avatars.githubusercontent.com/u/5395363?v=4?s=110" width="110px;" alt="Matt Tyree"/><br /><sub><b>Matt Tyree</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=Tyree" title="Documentation">📖</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
+1
-1
@@ -105,7 +105,7 @@ RUN \
|
|||||||
&& ln -fs "/var/lib/snipeit/keys/ldap_client_tls.cert" "/var/www/html/storage/ldap_client_tls.cert" \
|
&& ln -fs "/var/lib/snipeit/keys/ldap_client_tls.cert" "/var/www/html/storage/ldap_client_tls.cert" \
|
||||||
&& ln -fs "/var/lib/snipeit/keys/ldap_client_tls.key" "/var/www/html/storage/ldap_client_tls.key" \
|
&& ln -fs "/var/lib/snipeit/keys/ldap_client_tls.key" "/var/www/html/storage/ldap_client_tls.key" \
|
||||||
&& chown docker "/var/lib/snipeit/keys/" \
|
&& chown docker "/var/lib/snipeit/keys/" \
|
||||||
&& chown -h docker "/var/www/html/storage/" \
|
&& chown -Rh docker "/var/www/html/storage/" \
|
||||||
&& chmod +x /var/www/html/artisan \
|
&& chmod +x /var/www/html/artisan \
|
||||||
&& echo "Finished setting up application in /var/www/html"
|
&& echo "Finished setting up application in /var/www/html"
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||

|

|
||||||
|
|
||||||
[](https://crowdin.com/project/snipe-it) [](https://hub.docker.com/r/snipe/snipe-it/) [](https://twitter.com/snipeitapp) [](https://www.codacy.com/app/snipe/snipe-it?utm_source=github.com&utm_medium=referral&utm_content=snipe/snipe-it&utm_campaign=Badge_Grade) [](https://github.com/snipe/snipe-it/actions/workflows/tests.yml)
|
[](https://crowdin.com/project/snipe-it) [](https://hub.docker.com/r/snipe/snipe-it/) [](https://twitter.com/snipeitapp) [](https://app.codacy.com/gh/snipe/snipe-it/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade) [](https://github.com/snipe/snipe-it/actions/workflows/tests.yml)
|
||||||
[](#contributing) [](https://discord.gg/yZFtShAcKk)
|
[](#contributing) [](https://discord.gg/yZFtShAcKk)
|
||||||
|
|
||||||
## Snipe-IT - Open Source Asset Management System
|
## Snipe-IT - Open Source Asset Management System
|
||||||
|
|
||||||
This is a FOSS project for asset management in IT Operations. Knowing who has which laptop, when it was purchased in order to depreciate it correctly, handling software licenses, etc.
|
This is a FOSS project for asset management in IT Operations. Knowing who has which laptop, when it was purchased in order to depreciate it correctly, handling software licenses, etc.
|
||||||
|
|
||||||
It is built on [Laravel 8](http://laravel.com).
|
It is built on [Laravel 10](http://laravel.com).
|
||||||
|
|
||||||
Snipe-IT is actively developed and we [release quite frequently](https://github.com/snipe/snipe-it/releases). ([Check out the live demo here](https://snipeitapp.com/demo/).)
|
Snipe-IT is actively developed and we [release quite frequently](https://github.com/snipe/snipe-it/releases). ([Check out the live demo here](https://snipeitapp.com/demo/).)
|
||||||
|
|
||||||
__This is web-based software__. This means there is no executable file (aka no .exe files), and it must be run on a web server and accessed through a web browser. It runs on any Mac OSX, flavor of Linux, as well as Windows, and we have a [Docker image](https://snipe-it.readme.io/docs/docker) available if that's what you're into.
|
> [!TIP]
|
||||||
|
> __This is web-based software__. This means there is no executable file (aka no .exe files), and it must be run on a web server and accessed through a web browser. It runs on any Mac OSX, any flavor of Linux, as well as Windows, and we have a [Docker image](https://snipe-it.readme.io/docs/docker) available if that's what you're into.
|
||||||
|
|
||||||
-----
|
-----
|
||||||
|
|
||||||
@@ -21,7 +22,7 @@ For instructions on installing and configuring Snipe-IT on your server, check ou
|
|||||||
|
|
||||||
If you're having trouble with the installation, please check the [Common Issues](https://snipe-it.readme.io/docs/common-issues) and [Getting Help](https://snipe-it.readme.io/docs/getting-help) documentation, and search this repository's open *and* closed issues for help.
|
If you're having trouble with the installation, please check the [Common Issues](https://snipe-it.readme.io/docs/common-issues) and [Getting Help](https://snipe-it.readme.io/docs/getting-help) documentation, and search this repository's open *and* closed issues for help.
|
||||||
|
|
||||||
[](https://heroku.com/deploy)
|
<!-- [](https://heroku.com/deploy) -->
|
||||||
|
|
||||||
-----
|
-----
|
||||||
### User's Manual
|
### User's Manual
|
||||||
@@ -32,8 +33,9 @@ For help using Snipe-IT, check out the [user's manual](https://snipe-it.readme.i
|
|||||||
|
|
||||||
Feel free to check out the [GitHub Issues for this project](https://github.com/snipe/snipe-it/issues) to open a bug report or see what open issues you can help with. Please search through existing issues (open *and* closed) to see if your question has already been answered before opening a new issue.
|
Feel free to check out the [GitHub Issues for this project](https://github.com/snipe/snipe-it/issues) to open a bug report or see what open issues you can help with. Please search through existing issues (open *and* closed) to see if your question has already been answered before opening a new issue.
|
||||||
|
|
||||||
**PLEASE see the [Getting Help Guidelines](https://snipe-it.readme.io/docs/getting-help) and [Common Issues](https://snipe-it.readme.io/docs/common-issues) before opening a ticket, and be sure to complete all of the questions in the Github Issue template to help us to help you as quickly as possible.**
|
> [!IMPORTANT]
|
||||||
|
> **PLEASE see the [Getting Help Guidelines](https://snipe-it.readme.io/docs/getting-help) and [Common Issues](https://snipe-it.readme.io/docs/common-issues) before opening a ticket, and be sure to complete all of the questions in the Github Issue template to help us to help you as quickly as possible.**
|
||||||
|
>
|
||||||
-----
|
-----
|
||||||
|
|
||||||
### Upgrading
|
### Upgrading
|
||||||
@@ -57,6 +59,9 @@ Please see the [translations documentation](https://snipe-it.readme.io/docs/tran
|
|||||||
|
|
||||||
Since the release of the JSON REST API, several third-party developers have been developing modules and libraries to work with Snipe-IT.
|
Since the release of the JSON REST API, several third-party developers have been developing modules and libraries to work with Snipe-IT.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> As these were created by third-parties, Snipe-IT cannot provide support for these project, and you should contact the developers directly if you need assistance. Additionally, Snipe-IT makes no guarantees as to the reliability, accuracy or maintainability of these libraries. Use at your own risk. :)
|
||||||
|
|
||||||
- [Python Module](https://github.com/jbloomer/SnipeIT-PythonAPI) by [@jbloomer](https://github.com/jbloomer)
|
- [Python Module](https://github.com/jbloomer/SnipeIT-PythonAPI) by [@jbloomer](https://github.com/jbloomer)
|
||||||
- [SnipeSharp - .NET module in C#](https://github.com/barrycarey/SnipeSharp) by [@barrycarey](https://github.com/barrycarey)
|
- [SnipeSharp - .NET module in C#](https://github.com/barrycarey/SnipeSharp) by [@barrycarey](https://github.com/barrycarey)
|
||||||
- [InQRy -unmaintained-](https://github.com/Microsoft/InQRy) by [@Microsoft](https://github.com/Microsoft)
|
- [InQRy -unmaintained-](https://github.com/Microsoft/InQRy) by [@Microsoft](https://github.com/Microsoft)
|
||||||
@@ -73,8 +78,6 @@ Since the release of the JSON REST API, several third-party developers have been
|
|||||||
- [UniFi to Snipe-IT](https://github.com/RodneyLeeBrands/UnifiSnipeSync) by [@karpadiem](https://github.com/karpadiem) - Python script that synchronizes UniFi devices with Snipe-IT.
|
- [UniFi to Snipe-IT](https://github.com/RodneyLeeBrands/UnifiSnipeSync) by [@karpadiem](https://github.com/karpadiem) - Python script that synchronizes UniFi devices with Snipe-IT.
|
||||||
- [Kandji2Snipe](https://github.com/grokability/kandji2snipe) by [@briangoldstein](https://github.com/briangoldstein) - Python script that synchronizes Kandji with Snipe-IT.
|
- [Kandji2Snipe](https://github.com/grokability/kandji2snipe) by [@briangoldstein](https://github.com/briangoldstein) - Python script that synchronizes Kandji with Snipe-IT.
|
||||||
- [SnipeAgent](https://github.com/ReticentRobot/SnipeAgent) by @ReticentRobot - Windows agent for Snipe-IT
|
- [SnipeAgent](https://github.com/ReticentRobot/SnipeAgent) by @ReticentRobot - Windows agent for Snipe-IT
|
||||||
|
|
||||||
As these were created by third-parties, Snipe-IT cannot provide support for these project, and you should contact the developers directly if you need assistance. Additionally, Snipe-IT makes no guarantees as to the reliability, accuracy or maintainability of these libraries. Use at your own risk. :)
|
|
||||||
|
|
||||||
-----
|
-----
|
||||||
|
|
||||||
@@ -92,4 +95,5 @@ The ERD is available [online here](https://drawsql.app/templates/snipe-it).
|
|||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
To report a security vulnerability, please email security@snipeitapp.com instead of using the issue tracker.
|
> [!IMPORTANT]
|
||||||
|
> **To report a security vulnerability, please email security@snipeitapp.com instead of using the issue tracker.**
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
"description": "The maximum number of search results that can be returned at one time.",
|
"description": "The maximum number of search results that can be returned at one time.",
|
||||||
"value": "500"
|
"value": "500"
|
||||||
},
|
},
|
||||||
"MAIL_DRIVER": {
|
"MAIL_MAILER": {
|
||||||
"description": "Mail driver - Generally SMTP on Heroku - https://snipe-it.readme.io/docs/configuration#required-outgoing-mail-settings",
|
"description": "Mail driver - Generally SMTP on Heroku - https://snipe-it.readme.io/docs/configuration#required-outgoing-mail-settings",
|
||||||
"value": "smtp"
|
"value": "smtp"
|
||||||
},
|
},
|
||||||
@@ -58,9 +58,9 @@
|
|||||||
"description": "SMTP Server Password",
|
"description": "SMTP Server Password",
|
||||||
"value": "YOURPASSWORD"
|
"value": "YOURPASSWORD"
|
||||||
},
|
},
|
||||||
"MAIL_ENCRYPTION": {
|
"MAIL_TLS_VERIFY_PEER": {
|
||||||
"description": "Encryption protocol for email sending.",
|
"description": "Ensure validity of TLS certificate on remote mail server",
|
||||||
"value": "null"
|
"value": true
|
||||||
},
|
},
|
||||||
"MAIL_FROM_ADDR": {
|
"MAIL_FROM_ADDR": {
|
||||||
"description": "Email from address",
|
"description": "Email from address",
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use Illuminate\Console\Command;
|
|||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Laravel\Passport\TokenRepository;
|
use Laravel\Passport\TokenRepository;
|
||||||
use Illuminate\Contracts\Validation\Factory as ValidationFactory;
|
use Illuminate\Contracts\Validation\Factory as ValidationFactory;
|
||||||
use DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
class GeneratePersonalAccessToken extends Command
|
class GeneratePersonalAccessToken extends Command
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use App\Models\Setting;
|
|||||||
use App\Models\Ldap;
|
use App\Models\Ldap;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Models\Location;
|
use App\Models\Location;
|
||||||
use Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class LdapSync extends Command
|
class LdapSync extends Command
|
||||||
{
|
{
|
||||||
@@ -298,7 +298,7 @@ class LdapSync extends Command
|
|||||||
try {
|
try {
|
||||||
$ldap_manager = Ldap::findLdapUsers($item['manager'], -1, $this->option('filter'));
|
$ldap_manager = Ldap::findLdapUsers($item['manager'], -1, $this->option('filter'));
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
\Log::warning("Manager lookup caused an exception: " . $e->getMessage() . ". Falling back to direct username lookup");
|
Log::warning("Manager lookup caused an exception: " . $e->getMessage() . ". Falling back to direct username lookup");
|
||||||
// Hail-mary for Okta manager 'shortnames' - will only work if
|
// Hail-mary for Okta manager 'shortnames' - will only work if
|
||||||
// Okta configuration is using full email-address-style usernames
|
// Okta configuration is using full email-address-style usernames
|
||||||
$ldap_manager = [
|
$ldap_manager = [
|
||||||
@@ -390,7 +390,7 @@ class LdapSync extends Command
|
|||||||
$user->location_id = $location->id;
|
$user->location_id = $location->id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$location = null;
|
||||||
$user->ldap_import = 1;
|
$user->ldap_import = 1;
|
||||||
|
|
||||||
$errors = '';
|
$errors = '';
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace App\Console\Commands;
|
|||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
use Exception;
|
use Exception;
|
||||||
use Crypt;
|
use Illuminate\Support\Facades\Crypt;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a given ip is in a network
|
* Check if a given ip is in a network
|
||||||
@@ -160,7 +160,7 @@ class LdapTroubleshooter extends Command
|
|||||||
$output[] = "-x";
|
$output[] = "-x";
|
||||||
$output[] = "-b ".escapeshellarg($settings->ldap_basedn);
|
$output[] = "-b ".escapeshellarg($settings->ldap_basedn);
|
||||||
$output[] = "-D ".escapeshellarg($settings->ldap_uname);
|
$output[] = "-D ".escapeshellarg($settings->ldap_uname);
|
||||||
$output[] = "-w ".escapeshellarg(\Crypt::Decrypt($settings->ldap_pword));
|
$output[] = "-w ".escapeshellarg(Crypt::Decrypt($settings->ldap_pword));
|
||||||
$output[] = escapeshellarg(parenthesized_filter($settings->ldap_filter));
|
$output[] = escapeshellarg(parenthesized_filter($settings->ldap_filter));
|
||||||
if($settings->ldap_tls) {
|
if($settings->ldap_tls) {
|
||||||
$this->line("# adding STARTTLS option");
|
$this->line("# adding STARTTLS option");
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Console\Commands;
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use App\Events\UserMerged;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
@@ -51,7 +52,7 @@ class MergeUsersByUsername extends Command
|
|||||||
|
|
||||||
$bad_users = User::where('username', '=', trim($parts[0]))
|
$bad_users = User::where('username', '=', trim($parts[0]))
|
||||||
->whereNull('deleted_at')
|
->whereNull('deleted_at')
|
||||||
->with('assets', 'manager', 'userlog', 'licenses', 'consumables', 'accessories', 'managedLocations')
|
->with('assets', 'manager', 'userlog', 'licenses', 'consumables', 'accessories', 'managedLocations','uploads', 'acceptances')
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
|
|
||||||
@@ -105,10 +106,26 @@ class MergeUsersByUsername extends Command
|
|||||||
$managedLocation->save();
|
$managedLocation->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach ($bad_user->uploads as $upload) {
|
||||||
|
$this->info('Updating upload log record '.$upload->id.' to user '.$user->id);
|
||||||
|
$upload->item_id = $user->id;
|
||||||
|
$upload->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($bad_user->acceptances as $acceptance) {
|
||||||
|
$this->info('Updating acceptance log record '.$acceptance->id.' to user '.$user->id);
|
||||||
|
$acceptance->item_id = $user->id;
|
||||||
|
$acceptance->save();
|
||||||
|
}
|
||||||
|
|
||||||
// Mark the user as deleted
|
// Mark the user as deleted
|
||||||
$this->info('Marking the user as deleted');
|
$this->info('Marking the user as deleted');
|
||||||
$bad_user->deleted_at = Carbon::now()->timestamp;
|
$bad_user->deleted_at = Carbon::now()->timestamp;
|
||||||
$bad_user->save();
|
$bad_user->save();
|
||||||
|
|
||||||
|
event(new UserMerged($bad_user, $user, null));
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ namespace App\Console\Commands;
|
|||||||
|
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class MoveUploadsToNewDisk extends Command
|
class MoveUploadsToNewDisk extends Command
|
||||||
{
|
{
|
||||||
@@ -74,7 +75,7 @@ class MoveUploadsToNewDisk extends Command
|
|||||||
$new_url = Storage::disk('public')->url('uploads/'.$public_type.'/'.$filename, $filename);
|
$new_url = Storage::disk('public')->url('uploads/'.$public_type.'/'.$filename, $filename);
|
||||||
$this->info($type_count.'. PUBLIC: '.$filename.' was copied to '.$new_url);
|
$this->info($type_count.'. PUBLIC: '.$filename.' was copied to '.$new_url);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
\Log::debug($e);
|
Log::debug($e);
|
||||||
$this->error($e);
|
$this->error($e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,7 +117,7 @@ class MoveUploadsToNewDisk extends Command
|
|||||||
$new_url = Storage::url($private_type . '/' . $filename, $filename);
|
$new_url = Storage::url($private_type . '/' . $filename, $filename);
|
||||||
$this->info($type_count . '. PRIVATE: ' . $filename . ' was copied to ' . $new_url);
|
$this->info($type_count . '. PRIVATE: ' . $filename . ' was copied to ' . $new_url);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
\Log::debug($e);
|
Log::debug($e);
|
||||||
$this->error($e);
|
$this->error($e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -140,7 +141,7 @@ class MoveUploadsToNewDisk extends Command
|
|||||||
unlink($filename);
|
unlink($filename);
|
||||||
$public_delete_count++;
|
$public_delete_count++;
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
\Log::debug($e);
|
Log::debug($e);
|
||||||
$this->error($e);
|
$this->error($e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,7 +154,7 @@ class MoveUploadsToNewDisk extends Command
|
|||||||
unlink($filename);
|
unlink($filename);
|
||||||
$private_delete_count++;
|
$private_delete_count++;
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
\Log::debug($e);
|
Log::debug($e);
|
||||||
$this->error($e);
|
$this->error($e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ namespace App\Console\Commands;
|
|||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
ini_set('max_execution_time', env('IMPORT_TIME_LIMIT', 600)); //600 seconds = 10 minutes
|
ini_set('max_execution_time', env('IMPORT_TIME_LIMIT', 600)); //600 seconds = 10 minutes
|
||||||
ini_set('memory_limit', env('IMPORT_MEMORY_LIMIT', '500M'));
|
ini_set('memory_limit', env('IMPORT_MEMORY_LIMIT', '500M'));
|
||||||
@@ -59,7 +60,7 @@ class ObjectImportCommand extends Command
|
|||||||
|
|
||||||
// This $logFile/useFiles() bit is currently broken, so commenting it out for now
|
// This $logFile/useFiles() bit is currently broken, so commenting it out for now
|
||||||
// $logFile = $this->option('logfile');
|
// $logFile = $this->option('logfile');
|
||||||
// \Log::useFiles($logFile);
|
// Log::useFiles($logFile);
|
||||||
$this->comment('======= Importing Items from '.$filename.' =========');
|
$this->comment('======= Importing Items from '.$filename.' =========');
|
||||||
$importer->import();
|
$importer->import();
|
||||||
|
|
||||||
@@ -112,10 +113,10 @@ class ObjectImportCommand extends Command
|
|||||||
public function log($string, $level = 'info')
|
public function log($string, $level = 'info')
|
||||||
{
|
{
|
||||||
if ($level === 'warning') {
|
if ($level === 'warning') {
|
||||||
\Log::warning($string);
|
Log::warning($string);
|
||||||
$this->comment($string);
|
$this->comment($string);
|
||||||
} else {
|
} else {
|
||||||
\Log::Info($string);
|
Log::Info($string);
|
||||||
if ($this->option('verbose')) {
|
if ($this->option('verbose')) {
|
||||||
$this->comment($string);
|
$this->comment($string);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace App\Console\Commands;
|
|||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use App\Models\CustomField;
|
use App\Models\CustomField;
|
||||||
use Schema;
|
use Schema;
|
||||||
use DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
|
|
||||||
class PaveIt extends Command
|
class PaveIt extends Command
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ class RecryptFromMcrypt extends Command
|
|||||||
$this->comment('INFO: No LDAP password found. Skipping... ');
|
$this->comment('INFO: No LDAP password found. Skipping... ');
|
||||||
} else {
|
} else {
|
||||||
$decrypted_ldap_pword = $mcrypter->decrypt($settings->ldap_pword);
|
$decrypted_ldap_pword = $mcrypter->decrypt($settings->ldap_pword);
|
||||||
$settings->ldap_pword = \Crypt::encrypt($decrypted_ldap_pword);
|
$settings->ldap_pword = Crypt::encrypt($decrypted_ldap_pword);
|
||||||
$settings->save();
|
$settings->save();
|
||||||
}
|
}
|
||||||
/** @var CustomField[] $custom_fields */
|
/** @var CustomField[] $custom_fields */
|
||||||
@@ -132,7 +132,7 @@ class RecryptFromMcrypt extends Command
|
|||||||
// Try to decrypt the payload using the legacy app key
|
// Try to decrypt the payload using the legacy app key
|
||||||
try {
|
try {
|
||||||
$decrypted_field = $mcrypter->decrypt($asset->{$columnName});
|
$decrypted_field = $mcrypter->decrypt($asset->{$columnName});
|
||||||
$asset->{$columnName} = \Crypt::encrypt($decrypted_field);
|
$asset->{$columnName} = Crypt::encrypt($decrypted_field);
|
||||||
$this->comment($decrypted_field);
|
$this->comment($decrypted_field);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$errors[] = ' - ERROR: Could not decrypt field ['.$encrypted_field->name.']: '.$e->getMessage();
|
$errors[] = ' - ERROR: Could not decrypt field ['.$encrypted_field->name.']: '.$e->getMessage();
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ namespace App\Console\Commands;
|
|||||||
|
|
||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
use Artisan;
|
use Illuminate\Support\Facades\Artisan;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
|
|
||||||
class RegenerateAssetTags extends Command
|
class RegenerateAssetTags extends Command
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ use App\Models\Actionlog;
|
|||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use App\Models\License;
|
use App\Models\License;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Artisan;
|
use Illuminate\Support\Facades\Artisan;
|
||||||
use DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
|
|
||||||
class RestoreDeletedUsers extends Command
|
class RestoreDeletedUsers extends Command
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ namespace App\Console\Commands;
|
|||||||
|
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use ZipArchive;
|
use ZipArchive;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class SQLStreamer {
|
class SQLStreamer {
|
||||||
private $input;
|
private $input;
|
||||||
@@ -125,7 +126,7 @@ class SQLStreamer {
|
|||||||
while (($buffer = fgets($this->input, SQLStreamer::$buffer_size)) !== false) {
|
while (($buffer = fgets($this->input, SQLStreamer::$buffer_size)) !== false) {
|
||||||
$bytes_read += strlen($buffer);
|
$bytes_read += strlen($buffer);
|
||||||
if ($this->reading_beginning_of_line) {
|
if ($this->reading_beginning_of_line) {
|
||||||
// \Log::debug("Buffer is: '$buffer'");
|
// Log::debug("Buffer is: '$buffer'");
|
||||||
$cleaned_buffer = $this->parse_sql($buffer);
|
$cleaned_buffer = $this->parse_sql($buffer);
|
||||||
if ($this->output) {
|
if ($this->output) {
|
||||||
$bytes_written = fwrite($this->output, $cleaned_buffer);
|
$bytes_written = fwrite($this->output, $cleaned_buffer);
|
||||||
@@ -191,7 +192,7 @@ class RestoreFromBackup extends Command
|
|||||||
{
|
{
|
||||||
$dir = getcwd();
|
$dir = getcwd();
|
||||||
if( $dir != base_path() ) { // usually only the case when running via webserver, not via command-line
|
if( $dir != base_path() ) { // usually only the case when running via webserver, not via command-line
|
||||||
\Log::debug("Current working directory is: $dir, changing directory to: ".base_path());
|
Log::debug("Current working directory is: $dir, changing directory to: ".base_path());
|
||||||
chdir(base_path()); // TODO - is this *safe* to change on a running script?!
|
chdir(base_path()); // TODO - is this *safe* to change on a running script?!
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
@@ -297,7 +298,7 @@ class RestoreFromBackup extends Command
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (@pathinfo($raw_path, PATHINFO_EXTENSION) == 'sql') {
|
if (@pathinfo($raw_path, PATHINFO_EXTENSION) == 'sql') {
|
||||||
\Log::debug("Found a sql file!");
|
Log::debug("Found a sql file!");
|
||||||
$sqlfiles[] = $raw_path;
|
$sqlfiles[] = $raw_path;
|
||||||
$sqlfile_indices[] = $i;
|
$sqlfile_indices[] = $i;
|
||||||
continue;
|
continue;
|
||||||
@@ -413,7 +414,7 @@ class RestoreFromBackup extends Command
|
|||||||
$bytes_read = 0;
|
$bytes_read = 0;
|
||||||
while (($buffer = fgets($sql_contents, SQLStreamer::$buffer_size)) !== false) {
|
while (($buffer = fgets($sql_contents, SQLStreamer::$buffer_size)) !== false) {
|
||||||
$bytes_read += strlen($buffer);
|
$bytes_read += strlen($buffer);
|
||||||
// \Log::debug("Buffer is: '$buffer'");
|
// Log::debug("Buffer is: '$buffer'");
|
||||||
$bytes_written = fwrite($pipes[0], $buffer);
|
$bytes_written = fwrite($pipes[0], $buffer);
|
||||||
|
|
||||||
if ($bytes_written === false) {
|
if ($bytes_written === false) {
|
||||||
@@ -425,13 +426,13 @@ class RestoreFromBackup extends Command
|
|||||||
$bytes_read = $sql_importer->line_aware_piping();
|
$bytes_read = $sql_importer->line_aware_piping();
|
||||||
}
|
}
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
\Log::error("Error during restore!!!! ".$e->getMessage());
|
Log::error("Error during restore!!!! ".$e->getMessage());
|
||||||
// FIXME - put these back and/or put them in the right places?!
|
// FIXME - put these back and/or put them in the right places?!
|
||||||
$err_out = fgets($pipes[1]);
|
$err_out = fgets($pipes[1]);
|
||||||
$err_err = fgets($pipes[2]);
|
$err_err = fgets($pipes[2]);
|
||||||
\Log::error("Error OUTPUT: ".$err_out);
|
Log::error("Error OUTPUT: ".$err_out);
|
||||||
$this->info($err_out);
|
$this->info($err_out);
|
||||||
\Log::error("Error ERROR : ".$err_err);
|
Log::error("Error ERROR : ".$err_err);
|
||||||
$this->error($err_err);
|
$this->error($err_err);
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace App\Console\Commands;
|
|||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use App\Models\CustomField;
|
use App\Models\CustomField;
|
||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
use Artisan;
|
use Illuminate\Support\Facades\Artisan;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Illuminate\Contracts\Encryption\DecryptException;
|
use Illuminate\Contracts\Encryption\DecryptException;
|
||||||
use Illuminate\Encryption\Encrypter;
|
use Illuminate\Encryption\Encrypter;
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ class SendCurrentInventoryToUsers extends Command
|
|||||||
|
|
||||||
$count = 0;
|
$count = 0;
|
||||||
foreach ($users as $user) {
|
foreach ($users as $user) {
|
||||||
if (($user->assets->count() > 0) || ($user->accessories->count() > 0) || ($user->licenses->count() > 0)) {
|
if (($user->assets->count() > 0) || ($user->accessories->count() > 0) || ($user->licenses->count() > 0) || ($user->consumables->count() > 0)) {
|
||||||
$count++;
|
$count++;
|
||||||
$user->notify((new CurrentInventory($user)));
|
$user->notify((new CurrentInventory($user)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ use App\Notifications\ExpectedCheckinAdminNotification;
|
|||||||
use App\Notifications\ExpectedCheckinNotification;
|
use App\Notifications\ExpectedCheckinNotification;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
|
|
||||||
class SendExpectedCheckinAlerts extends Command
|
class SendExpectedCheckinAlerts extends Command
|
||||||
{
|
{
|
||||||
@@ -43,25 +42,31 @@ class SendExpectedCheckinAlerts extends Command
|
|||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
$settings = Setting::getSettings();
|
$settings = Setting::getSettings();
|
||||||
$whenNotify = Carbon::now();
|
$interval = $settings->audit_warning_days ?? 0;
|
||||||
$assets = Asset::with('assignedTo')->whereNotNull('assigned_to')->whereNotNull('expected_checkin')->where('expected_checkin', '<=', $whenNotify)->get();
|
$today = Carbon::now();
|
||||||
|
$interval_date = $today->copy()->addDays($interval);
|
||||||
|
|
||||||
|
$assets = Asset::whereNull('deleted_at')->DueOrOverdueForCheckin($settings)->orderBy('assets.expected_checkin', 'desc')->get();
|
||||||
|
|
||||||
|
$this->info($assets->count().' assets must be checked in on or before '.$interval_date.' is deadline');
|
||||||
|
|
||||||
$this->info($whenNotify.' is deadline');
|
|
||||||
$this->info($assets->count().' assets');
|
|
||||||
|
|
||||||
foreach ($assets as $asset) {
|
foreach ($assets as $asset) {
|
||||||
if ($asset->assigned && $asset->checkedOutToUser()) {
|
if ($asset->assignedTo && (isset($asset->assignedTo->email)) && ($asset->assignedTo->email!='') && $asset->checkedOutToUser()) {
|
||||||
Log::info('Sending ExpectedCheckinNotification to ' . $asset->assigned->email);
|
$this->info('Sending User ExpectedCheckinNotification to: '.$asset->assignedTo->email);
|
||||||
$asset->assigned->notify((new ExpectedCheckinNotification($asset)));
|
$asset->assignedTo->notify((new ExpectedCheckinNotification($asset)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($assets) && ($assets->count() > 0) && ($settings->alert_email != '')) {
|
if (($assets) && ($assets->count() > 0) && ($settings->alert_email != '')) {
|
||||||
// Send a rollup to the admin, if settings dictate
|
// Send a rollup to the admin, if settings dictate
|
||||||
$recipients = collect(explode(',', $settings->alert_email))->map(function ($item, $key) {
|
$recipients = collect(explode(',', $settings->alert_email))->map(function ($item) {
|
||||||
return new AlertRecipient($item);
|
return new AlertRecipient($item);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$this->info('Sending Admin ExpectedCheckinNotification to: '.$settings->alert_email);
|
||||||
\Notification::send($recipients, new ExpectedCheckinAdminNotification($assets));
|
\Notification::send($recipients, new ExpectedCheckinAdminNotification($assets));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,13 +3,11 @@
|
|||||||
namespace App\Console\Commands;
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use App\Models\License;
|
use App\Models\Recipients\AlertRecipient;
|
||||||
use App\Models\Recipients;
|
|
||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
use App\Notifications\ExpiringAssetsNotification;
|
|
||||||
use App\Notifications\SendUpcomingAuditNotification;
|
use App\Notifications\SendUpcomingAuditNotification;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
|
|
||||||
class SendUpcomingAuditReport extends Command
|
class SendUpcomingAuditReport extends Command
|
||||||
@@ -46,39 +44,24 @@ class SendUpcomingAuditReport extends Command
|
|||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
$settings = Setting::getSettings();
|
$settings = Setting::getSettings();
|
||||||
|
$interval = $settings->audit_warning_days ?? 0;
|
||||||
|
$today = Carbon::now();
|
||||||
|
$interval_date = $today->copy()->addDays($interval);
|
||||||
|
|
||||||
if (($settings->alert_email != '') && ($settings->audit_warning_days) && ($settings->alerts_enabled == 1)) {
|
$assets = Asset::whereNull('deleted_at')->DueOrOverdueForAudit($settings)->orderBy('assets.next_audit_date', 'desc')->get();
|
||||||
|
$this->info($assets->count().' assets must be audited in on or before '.$interval_date.' is deadline');
|
||||||
|
|
||||||
|
|
||||||
|
if (($assets) && ($assets->count() > 0) && ($settings->alert_email != '')) {
|
||||||
// Send a rollup to the admin, if settings dictate
|
// Send a rollup to the admin, if settings dictate
|
||||||
$recipients = collect(explode(',', $settings->alert_email))->map(function ($item, $key) {
|
$recipients = collect(explode(',', $settings->alert_email))->map(function ($item) {
|
||||||
return new \App\Models\Recipients\AlertRecipient($item);
|
return new AlertRecipient($item);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Assets due for auditing
|
$this->info('Sending Admin SendUpcomingAuditNotification to: '.$settings->alert_email);
|
||||||
|
\Notification::send($recipients, new SendUpcomingAuditNotification($assets, $settings->audit_warning_days));
|
||||||
|
|
||||||
$assets = Asset::whereNotNull('next_audit_date')
|
|
||||||
->DueOrOverdueForAudit($settings)
|
|
||||||
->orderBy('last_audit_date', 'asc')->get();
|
|
||||||
|
|
||||||
if ($assets->count() > 0) {
|
|
||||||
$this->info(trans_choice('mail.upcoming-audits', $assets->count(),
|
|
||||||
['count' => $assets->count(), 'threshold' => $settings->audit_warning_days]));
|
|
||||||
\Notification::send($recipients, new SendUpcomingAuditNotification($assets, $settings->audit_warning_days));
|
|
||||||
$this->info('Audit report sent to '.$settings->alert_email);
|
|
||||||
} else {
|
|
||||||
$this->info('No assets to be audited. No report sent.');
|
|
||||||
}
|
|
||||||
} elseif ($settings->alert_email == '') {
|
|
||||||
$this->error('Could not send email. No alert email configured in settings');
|
|
||||||
} elseif (! $settings->audit_warning_days) {
|
|
||||||
$this->error('No audit warning days set in Admin Notifications. No mail will be sent.');
|
|
||||||
} elseif ($settings->alerts_enabled != 1) {
|
|
||||||
$this->info('Alerts are disabled in the settings. No mail will be sent');
|
|
||||||
} else {
|
|
||||||
$this->error('Something went wrong. :( ');
|
|
||||||
$this->error('Admin Notifications Email Setting: '.$settings->alert_email);
|
|
||||||
$this->error('Admin Audit Warning Setting: '.$settings->audit_warning_days);
|
|
||||||
$this->error('Admin Alerts Emnabled: '.$settings->alerts_enabled);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ namespace App\Console\Commands;
|
|||||||
|
|
||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class SyncAssetCounters extends Command
|
class SyncAssetCounters extends Command
|
||||||
{
|
{
|
||||||
@@ -58,7 +59,7 @@ class SyncAssetCounters extends Command
|
|||||||
$asset->save();
|
$asset->save();
|
||||||
$bar->advance();
|
$bar->advance();
|
||||||
|
|
||||||
\Log::debug('Asset: '.$asset->id.' has '.$asset->checkin_counter.' checkins, '.$asset->checkout_counter.' checkouts, and '.$asset->requests_counter.' requests');
|
Log::debug('Asset: '.$asset->id.' has '.$asset->checkin_counter.' checkins, '.$asset->checkout_counter.' checkouts, and '.$asset->requests_counter.' requests');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use App\Models\Asset;
|
||||||
|
use App\Models\CustomField;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
|
class ToggleCustomfieldEncryption extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'snipeit:customfield-encryption
|
||||||
|
{fieldname : the db_column_name of the field}';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'This command should be used to convert an unencrypted custom field into a custom field and encrypt the associated data in the assets table for that column.';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new command instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$fieldname = $this->argument('fieldname');
|
||||||
|
|
||||||
|
if ($field = CustomField::where('db_column', $fieldname)->first()) {
|
||||||
|
|
||||||
|
// If the field is not encrypted, make it encrypted and encrypt the data in the assets table for the
|
||||||
|
// corresponding field.
|
||||||
|
DB::transaction(function () use ($field) {
|
||||||
|
|
||||||
|
if ($field->field_encrypted == 0) {
|
||||||
|
$assets = Asset::whereNotNull($field->db_column)->get();
|
||||||
|
|
||||||
|
foreach ($assets as $asset) {
|
||||||
|
$asset->{$field->db_column} = encrypt($asset->{$field->db_column});
|
||||||
|
$asset->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
$field->field_encrypted = 1;
|
||||||
|
$field->save();
|
||||||
|
|
||||||
|
// This field is already encrypted. Do nothing.
|
||||||
|
} else {
|
||||||
|
$this->error('The custom field ' . $field->db_column.' is already encrypted. No action was taken.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// No matching column name found
|
||||||
|
} else {
|
||||||
|
$this->error('No matching results for unencrypted custom fields with db_column name: ' . $fieldname.'. Please check the fieldname.');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@ class UserMerged
|
|||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function __construct(User $from_user, User $to_user, User $admin)
|
public function __construct(User $from_user, User $to_user, ?User $admin)
|
||||||
{
|
{
|
||||||
$this->merged_from = $from_user;
|
$this->merged_from = $from_user;
|
||||||
$this->merged_to = $to_user;
|
$this->merged_to = $to_user;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use App\Helpers\Helper;
|
|||||||
use Illuminate\Validation\ValidationException;
|
use Illuminate\Validation\ValidationException;
|
||||||
use Illuminate\Auth\AuthenticationException;
|
use Illuminate\Auth\AuthenticationException;
|
||||||
use ArieTimmerman\Laravel\SCIMServer\Exceptions\SCIMException;
|
use ArieTimmerman\Laravel\SCIMServer\Exceptions\SCIMException;
|
||||||
use Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
use JsonException;
|
use JsonException;
|
||||||
use Carbon\Exceptions\InvalidFormatException;
|
use Carbon\Exceptions\InvalidFormatException;
|
||||||
@@ -44,8 +44,8 @@ class Handler extends ExceptionHandler
|
|||||||
public function report(Throwable $exception)
|
public function report(Throwable $exception)
|
||||||
{
|
{
|
||||||
if ($this->shouldReport($exception)) {
|
if ($this->shouldReport($exception)) {
|
||||||
if (class_exists(\Log::class)) {
|
if (class_exists(Log::class)) {
|
||||||
\Log::error($exception);
|
Log::error($exception);
|
||||||
}
|
}
|
||||||
return parent::report($exception);
|
return parent::report($exception);
|
||||||
}
|
}
|
||||||
|
|||||||
+52
-9
@@ -12,10 +12,12 @@ use App\Models\Depreciation;
|
|||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
use App\Models\Statuslabel;
|
use App\Models\Statuslabel;
|
||||||
use App\Models\License;
|
use App\Models\License;
|
||||||
use Crypt;
|
use Illuminate\Support\Facades\Crypt;
|
||||||
use Illuminate\Contracts\Encryption\DecryptException;
|
use Illuminate\Contracts\Encryption\DecryptException;
|
||||||
use Image;
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Intervention\Image\ImageManagerStatic as Image;
|
||||||
|
use Illuminate\Support\Facades\Session;
|
||||||
|
|
||||||
class Helper
|
class Helper
|
||||||
{
|
{
|
||||||
@@ -412,7 +414,7 @@ class Helper
|
|||||||
|
|
||||||
if ($index >= $total_colors) {
|
if ($index >= $total_colors) {
|
||||||
|
|
||||||
\Log::info('Status label count is '.$index.' and exceeds the allowed count of 266.');
|
Log::info('Status label count is '.$index.' and exceeds the allowed count of 266.');
|
||||||
//patch fix for array key overflow (color count starts at 1, array starts at 0)
|
//patch fix for array key overflow (color count starts at 1, array starts at 0)
|
||||||
$index = $index - $total_colors - 1;
|
$index = $index - $total_colors - 1;
|
||||||
|
|
||||||
@@ -842,7 +844,7 @@ class Helper
|
|||||||
$filetype = @finfo_file($finfo, $file);
|
$filetype = @finfo_file($finfo, $file);
|
||||||
finfo_close($finfo);
|
finfo_close($finfo);
|
||||||
|
|
||||||
if (($filetype == 'image/jpeg') || ($filetype == 'image/jpg') || ($filetype == 'image/png') || ($filetype == 'image/bmp') || ($filetype == 'image/gif')) {
|
if (($filetype == 'image/jpeg') || ($filetype == 'image/jpg') || ($filetype == 'image/png') || ($filetype == 'image/bmp') || ($filetype == 'image/gif') || ($filetype == 'image/avif')) {
|
||||||
return $filetype;
|
return $filetype;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -875,12 +877,15 @@ class Helper
|
|||||||
$permission_name = $permission[$x]['permission'];
|
$permission_name = $permission[$x]['permission'];
|
||||||
|
|
||||||
if ($permission[$x]['display'] === true) {
|
if ($permission[$x]['display'] === true) {
|
||||||
if ($selected_arr) {
|
|
||||||
|
if (is_array($selected_arr)) {
|
||||||
|
|
||||||
if (array_key_exists($permission_name, $selected_arr)) {
|
if (array_key_exists($permission_name, $selected_arr)) {
|
||||||
$permissions_arr[$permission_name] = $selected_arr[$permission_name];
|
$permissions_arr[$permission_name] = $selected_arr[$permission_name];
|
||||||
} else {
|
} else {
|
||||||
$permissions_arr[$permission_name] = '0';
|
$permissions_arr[$permission_name] = '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$permissions_arr[$permission_name] = '0';
|
$permissions_arr[$permission_name] = '0';
|
||||||
}
|
}
|
||||||
@@ -1012,7 +1017,7 @@ class Helper
|
|||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$tmp_date = new \Carbon($date);
|
$tmp_date = new Carbon($date);
|
||||||
|
|
||||||
if ($type == 'datetime') {
|
if ($type == 'datetime') {
|
||||||
$dt['datetime'] = $tmp_date->format('Y-m-d H:i:s');
|
$dt['datetime'] = $tmp_date->format('Y-m-d H:i:s');
|
||||||
@@ -1029,7 +1034,7 @@ class Helper
|
|||||||
return $dt['formatted'];
|
return $dt['formatted'];
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
\Log::warning($e);
|
Log::warning($e);
|
||||||
return $date.' (Invalid '.$type.' value.)';
|
return $date.' (Invalid '.$type.' value.)';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1106,6 +1111,8 @@ class Helper
|
|||||||
'jpeg' => 'far fa-image',
|
'jpeg' => 'far fa-image',
|
||||||
'gif' => 'far fa-image',
|
'gif' => 'far fa-image',
|
||||||
'png' => 'far fa-image',
|
'png' => 'far fa-image',
|
||||||
|
'webp' => 'far fa-image',
|
||||||
|
'avif' => 'far fa-image',
|
||||||
// word
|
// word
|
||||||
'doc' => 'far fa-file-word',
|
'doc' => 'far fa-file-word',
|
||||||
'docx' => 'far fa-file-word',
|
'docx' => 'far fa-file-word',
|
||||||
@@ -1141,6 +1148,8 @@ class Helper
|
|||||||
case 'jpeg':
|
case 'jpeg':
|
||||||
case 'gif':
|
case 'gif':
|
||||||
case 'png':
|
case 'png':
|
||||||
|
case 'webp':
|
||||||
|
case 'avif':
|
||||||
return true;
|
return true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -1338,7 +1347,7 @@ class Helper
|
|||||||
public static function isDemoMode() {
|
public static function isDemoMode() {
|
||||||
if (config('app.lock_passwords') === true) {
|
if (config('app.lock_passwords') === true) {
|
||||||
return true;
|
return true;
|
||||||
\Log::debug('app locked!');
|
Log::debug('app locked!');
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -1431,7 +1440,7 @@ class Helper
|
|||||||
|
|
||||||
foreach (self::$language_map as $legacy => $new) {
|
foreach (self::$language_map as $legacy => $new) {
|
||||||
if ($language_code == $legacy) {
|
if ($language_code == $legacy) {
|
||||||
\Log::debug('Current language is '.$legacy.', using '.$new.' instead');
|
Log::debug('Current language is '.$legacy.', using '.$new.' instead');
|
||||||
return $new;
|
return $new;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1455,4 +1464,38 @@ class Helper
|
|||||||
return $new_locale; // better that you have some weird locale that doesn't fit into our mappings anywhere than 'void'
|
return $new_locale; // better that you have some weird locale that doesn't fit into our mappings anywhere than 'void'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static public function getRedirectOption($request, $id, $table, $asset_id = null)
|
||||||
|
{
|
||||||
|
|
||||||
|
$redirect_option = Session::get('redirect_option');
|
||||||
|
$checkout_to_type = Session::get('checkout_to_type');
|
||||||
|
|
||||||
|
//return to index
|
||||||
|
if ($redirect_option == '0') {
|
||||||
|
switch ($table) {
|
||||||
|
case "Assets":
|
||||||
|
return redirect()->route('hardware.index')->with('success', trans('admin/hardware/message.checkout.success'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//return to thing being assigned
|
||||||
|
if ($redirect_option == '1') {
|
||||||
|
switch ($table) {
|
||||||
|
case "Assets":
|
||||||
|
return redirect()->route('hardware.show', $id ? $id : $asset_id)->with('success', trans('admin/hardware/message.checkout.success'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//return to thing being assigned to
|
||||||
|
if ($redirect_option == '2') {
|
||||||
|
switch ($checkout_to_type) {
|
||||||
|
case 'user':
|
||||||
|
return redirect()->route('users.show', $request->assigned_user)->with('success', trans('admin/hardware/message.checkout.success'));
|
||||||
|
case 'location':
|
||||||
|
return redirect()->route('locations.show', $request->assigned_location)->with('success', trans('admin/hardware/message.checkout.success'));
|
||||||
|
case 'asset':
|
||||||
|
return redirect()->route('hardware.show', $request->assigned_asset)->with('success', trans('admin/hardware/message.checkout.success'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return redirect()->back()->with('error', trans('admin/hardware/message.checkout.error'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ use Illuminate\Support\Facades\Auth;
|
|||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Redirect;
|
use Redirect;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
/** This controller handles all actions related to Accessories for
|
/** This controller handles all actions related to Accessories for
|
||||||
* the Snipe-IT Asset Management application.
|
* the Snipe-IT Asset Management application.
|
||||||
@@ -57,7 +58,7 @@ class AccessoriesController extends Controller
|
|||||||
*
|
*
|
||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @param ImageUploadRequest $request
|
* @param ImageUploadRequest $request
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
*/
|
*/
|
||||||
public function store(ImageUploadRequest $request)
|
public function store(ImageUploadRequest $request)
|
||||||
@@ -150,7 +151,7 @@ class AccessoriesController extends Controller
|
|||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @param ImageUploadRequest $request
|
* @param ImageUploadRequest $request
|
||||||
* @param int $accessoryId
|
* @param int $accessoryId
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
*/
|
*/
|
||||||
public function update(ImageUploadRequest $request, $accessoryId = null)
|
public function update(ImageUploadRequest $request, $accessoryId = null)
|
||||||
@@ -204,7 +205,7 @@ class AccessoriesController extends Controller
|
|||||||
*
|
*
|
||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @param int $accessoryId
|
* @param int $accessoryId
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
*/
|
*/
|
||||||
public function destroy($accessoryId)
|
public function destroy($accessoryId)
|
||||||
@@ -224,7 +225,7 @@ class AccessoriesController extends Controller
|
|||||||
try {
|
try {
|
||||||
Storage::disk('public')->delete('accessories'.'/'.$accessory->image);
|
Storage::disk('public')->delete('accessories'.'/'.$accessory->image);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
\Log::debug($e);
|
Log::debug($e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use App\Models\Accessory;
|
|||||||
use Illuminate\Support\Facades\Response;
|
use Illuminate\Support\Facades\Response;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Symfony\Accessory\HttpFoundation\JsonResponse;
|
use Symfony\Accessory\HttpFoundation\JsonResponse;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class AccessoriesFilesController extends Controller
|
class AccessoriesFilesController extends Controller
|
||||||
{
|
{
|
||||||
@@ -85,7 +86,7 @@ class AccessoriesFilesController extends Controller
|
|||||||
try {
|
try {
|
||||||
Storage::delete('accessories/'.$log->filename);
|
Storage::delete('accessories/'.$log->filename);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
\Log::debug($e);
|
Log::debug($e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,7 +113,7 @@ class AccessoriesFilesController extends Controller
|
|||||||
public function show($accessoryId = null, $fileId = null, $download = true)
|
public function show($accessoryId = null, $fileId = null, $download = true)
|
||||||
{
|
{
|
||||||
|
|
||||||
\Log::debug('Private filesystem is: '.config('filesystems.default'));
|
Log::debug('Private filesystem is: '.config('filesystems.default'));
|
||||||
$accessory = Accessory::find($accessoryId);
|
$accessory = Accessory::find($accessoryId);
|
||||||
|
|
||||||
|
|
||||||
@@ -129,8 +130,8 @@ class AccessoriesFilesController extends Controller
|
|||||||
$file = 'private_uploads/accessories/'.$log->filename;
|
$file = 'private_uploads/accessories/'.$log->filename;
|
||||||
|
|
||||||
if (Storage::missing($file)) {
|
if (Storage::missing($file)) {
|
||||||
\Log::debug('FILE DOES NOT EXISTS for '.$file);
|
Log::debug('FILE DOES NOT EXISTS for '.$file);
|
||||||
\Log::debug('URL should be '.Storage::url($file));
|
Log::debug('URL should be '.Storage::url($file));
|
||||||
|
|
||||||
return response('File '.$file.' ('.Storage::url($file).') not found on server', 404)
|
return response('File '.$file.' ('.Storage::url($file).') not found on server', 404)
|
||||||
->header('Content-Type', 'text/plain');
|
->header('Content-Type', 'text/plain');
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ class AccessoryCheckinController extends Controller
|
|||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @param null $accessoryUserId
|
* @param null $accessoryUserId
|
||||||
* @param string $backto
|
* @param string $backto
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
* @internal param int $accessoryId
|
* @internal param int $accessoryId
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ class AccessoryCheckoutController extends Controller
|
|||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @param int $accessoryId
|
* @param int $accessoryId
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
*/
|
*/
|
||||||
public function store(Request $request, $accessoryId)
|
public function store(Request $request, $accessoryId)
|
||||||
|
|||||||
@@ -23,13 +23,13 @@ use App\Notifications\AcceptanceAssetAcceptedNotification;
|
|||||||
use App\Notifications\AcceptanceAssetDeclinedNotification;
|
use App\Notifications\AcceptanceAssetDeclinedNotification;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use App\Http\Controllers\SettingsController;
|
use App\Http\Controllers\SettingsController;
|
||||||
use Barryvdh\DomPDF\Facade\Pdf;
|
use Barryvdh\DomPDF\Facade\Pdf;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use phpDocumentor\Reflection\Types\Compound;
|
use phpDocumentor\Reflection\Types\Compound;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class AcceptanceController extends Controller
|
class AcceptanceController extends Controller
|
||||||
{
|
{
|
||||||
@@ -80,7 +80,7 @@ class AcceptanceController extends Controller
|
|||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @param int $id
|
* @param int $id
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function store(Request $request, $id)
|
public function store(Request $request, $id)
|
||||||
{
|
{
|
||||||
@@ -223,6 +223,7 @@ class AcceptanceController extends Controller
|
|||||||
'item_model' => $display_model,
|
'item_model' => $display_model,
|
||||||
'item_serial' => $item->serial,
|
'item_serial' => $item->serial,
|
||||||
'eula' => $item->getEula(),
|
'eula' => $item->getEula(),
|
||||||
|
'note' => $request->input('note'),
|
||||||
'check_out_date' => Carbon::parse($acceptance->created_at)->format('Y-m-d'),
|
'check_out_date' => Carbon::parse($acceptance->created_at)->format('Y-m-d'),
|
||||||
'accepted_date' => Carbon::parse($acceptance->accepted_at)->format('Y-m-d'),
|
'accepted_date' => Carbon::parse($acceptance->accepted_at)->format('Y-m-d'),
|
||||||
'assigned_to' => $assigned_to,
|
'assigned_to' => $assigned_to,
|
||||||
@@ -233,12 +234,12 @@ class AcceptanceController extends Controller
|
|||||||
];
|
];
|
||||||
|
|
||||||
if ($pdf_view_route!='') {
|
if ($pdf_view_route!='') {
|
||||||
\Log::debug($pdf_filename.' is the filename, and the route was specified.');
|
Log::debug($pdf_filename.' is the filename, and the route was specified.');
|
||||||
$pdf = Pdf::loadView($pdf_view_route, $data);
|
$pdf = Pdf::loadView($pdf_view_route, $data);
|
||||||
Storage::put('private_uploads/eula-pdfs/' .$pdf_filename, $pdf->output());
|
Storage::put('private_uploads/eula-pdfs/' .$pdf_filename, $pdf->output());
|
||||||
}
|
}
|
||||||
|
|
||||||
$acceptance->accept($sig_filename, $item->getEula(), $pdf_filename);
|
$acceptance->accept($sig_filename, $item->getEula(), $pdf_filename, $request->input('note'));
|
||||||
$acceptance->notify(new AcceptanceAssetAcceptedNotification($data));
|
$acceptance->notify(new AcceptanceAssetAcceptedNotification($data));
|
||||||
event(new CheckoutAccepted($acceptance));
|
event(new CheckoutAccepted($acceptance));
|
||||||
|
|
||||||
@@ -306,10 +307,12 @@ class AcceptanceController extends Controller
|
|||||||
$assigned_to = User::find($acceptance->assigned_to_id)->present()->fullName;
|
$assigned_to = User::find($acceptance->assigned_to_id)->present()->fullName;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'item_tag' => $item->asset_tag,
|
'item_tag' => $item->asset_tag,
|
||||||
'item_model' => $display_model,
|
'item_model' => $display_model,
|
||||||
'item_serial' => $item->serial,
|
'item_serial' => $item->serial,
|
||||||
|
'note' => $request->input('note'),
|
||||||
'declined_date' => Carbon::parse($acceptance->declined_at)->format('Y-m-d'),
|
'declined_date' => Carbon::parse($acceptance->declined_at)->format('Y-m-d'),
|
||||||
'signature' => ($sig_filename) ? storage_path() . '/private_uploads/signatures/' . $sig_filename : null,
|
'signature' => ($sig_filename) ? storage_path() . '/private_uploads/signatures/' . $sig_filename : null,
|
||||||
'assigned_to' => $assigned_to,
|
'assigned_to' => $assigned_to,
|
||||||
@@ -318,12 +321,12 @@ class AcceptanceController extends Controller
|
|||||||
];
|
];
|
||||||
|
|
||||||
if ($pdf_view_route!='') {
|
if ($pdf_view_route!='') {
|
||||||
\Log::debug($pdf_filename.' is the filename, and the route was specified.');
|
Log::debug($pdf_filename.' is the filename, and the route was specified.');
|
||||||
$pdf = Pdf::loadView($pdf_view_route, $data);
|
$pdf = Pdf::loadView($pdf_view_route, $data);
|
||||||
Storage::put('private_uploads/eula-pdfs/' .$pdf_filename, $pdf->output());
|
Storage::put('private_uploads/eula-pdfs/' .$pdf_filename, $pdf->output());
|
||||||
}
|
}
|
||||||
|
|
||||||
$acceptance->decline($sig_filename);
|
$acceptance->decline($sig_filename, $request->input('note'));
|
||||||
$acceptance->notify(new AcceptanceAssetDeclinedNotification($data));
|
$acceptance->notify(new AcceptanceAssetDeclinedNotification($data));
|
||||||
event(new CheckoutDeclined($acceptance));
|
event(new CheckoutDeclined($acceptance));
|
||||||
$return_msg = trans('admin/users/message.declined');
|
$return_msg = trans('admin/users/message.declined');
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ namespace App\Http\Controllers;
|
|||||||
|
|
||||||
use App\Helpers\Helper;
|
use App\Helpers\Helper;
|
||||||
use App\Models\Actionlog;
|
use App\Models\Actionlog;
|
||||||
use Response;
|
use Illuminate\Support\Facades\Response;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
class ActionlogController extends Controller
|
class ActionlogController extends Controller
|
||||||
{
|
{
|
||||||
public function displaySig($filename)
|
public function displaySig($filename)
|
||||||
@@ -14,19 +15,26 @@ class ActionlogController extends Controller
|
|||||||
// file_get_contents, so we set the error reporting for just this class
|
// file_get_contents, so we set the error reporting for just this class
|
||||||
error_reporting(0);
|
error_reporting(0);
|
||||||
|
|
||||||
$this->authorize('view', \App\Models\Asset::class);
|
$disk = config('filesystems.default');
|
||||||
$file = config('app.private_uploads').'/signatures/'.$filename;
|
switch (config("filesystems.disks.$disk.driver")) {
|
||||||
$filetype = Helper::checkUploadIsImage($file);
|
case 's3':
|
||||||
|
$file = 'private_uploads/signatures/'.$filename;
|
||||||
|
return redirect()->away(Storage::disk($disk)->temporaryUrl($file, now()->addMinutes(5)));
|
||||||
|
default:
|
||||||
|
$this->authorize('view', \App\Models\Asset::class);
|
||||||
|
$file = config('app.private_uploads').'/signatures/'.$filename;
|
||||||
|
$filetype = Helper::checkUploadIsImage($file);
|
||||||
|
|
||||||
$contents = file_get_contents($file, false, stream_context_create(['http' => ['ignore_errors' => true]]));
|
$contents = file_get_contents($file, false, stream_context_create(['http' => ['ignore_errors' => true]]));
|
||||||
if ($contents === false) {
|
if ($contents === false) {
|
||||||
\Log::warn('File '.$file.' not found');
|
Log::warning('File '.$file.' not found');
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return Response::make($contents)->header('Content-Type', $filetype);
|
return Response::make($contents)->header('Content-Type', $filetype);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getStoredEula($filename){
|
public function getStoredEula($filename){
|
||||||
$this->authorize('view', \App\Models\Asset::class);
|
$this->authorize('view', \App\Models\Asset::class);
|
||||||
$file = config('app.private_uploads').'/eula-pdfs/'.$filename;
|
$file = config('app.private_uploads').'/eula-pdfs/'.$filename;
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ use App\Http\Transformers\SelectlistTransformer;
|
|||||||
use App\Models\Accessory;
|
use App\Models\Accessory;
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Http\Requests\ImageUploadRequest;
|
use App\Http\Requests\ImageUploadRequest;
|
||||||
|
|
||||||
@@ -274,7 +274,7 @@ class AccessoriesController extends Controller
|
|||||||
*
|
*
|
||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @param int $accessoryId
|
* @param int $accessoryId
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function checkout(Request $request, $accessoryId)
|
public function checkout(Request $request, $accessoryId)
|
||||||
{
|
{
|
||||||
@@ -320,7 +320,7 @@ class AccessoriesController extends Controller
|
|||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @param int $accessoryUserId
|
* @param int $accessoryUserId
|
||||||
* @param string $backto
|
* @param string $backto
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
* @internal param int $accessoryId
|
* @internal param int $accessoryId
|
||||||
*/
|
*/
|
||||||
public function checkin(Request $request, $accessoryUserId = null)
|
public function checkin(Request $request, $accessoryUserId = null)
|
||||||
|
|||||||
@@ -0,0 +1,219 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Helpers\StorageHelper;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Support\Facades\Crypt;
|
||||||
|
use Illuminate\Support\Facades\Gate;
|
||||||
|
use App\Helpers\Helper;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\Asset;
|
||||||
|
use App\Models\AssetModel;
|
||||||
|
use App\Models\Actionlog;
|
||||||
|
use \Illuminate\Support\Facades\Auth;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use DB;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use App\Http\Requests\UploadFileRequest;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Input;
|
||||||
|
use Paginator;
|
||||||
|
use Slack;
|
||||||
|
use Str;
|
||||||
|
use TCPDF;
|
||||||
|
use Validator;
|
||||||
|
use Route;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class controls file related actions related
|
||||||
|
* to assets for the Snipe-IT Asset Management application.
|
||||||
|
*
|
||||||
|
* Based on the Assets/AssetFilesController by A. Gianotto <snipe@snipe.net>
|
||||||
|
*
|
||||||
|
* @version v1.0
|
||||||
|
* @author [T. Scarsbrook] [<snipe@scarzybrook.co.uk>]
|
||||||
|
*/
|
||||||
|
class AssetFilesController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Accepts a POST to upload a file to the server.
|
||||||
|
*
|
||||||
|
* @param \App\Http\Requests\UploadFileRequest $request
|
||||||
|
* @param int $assetId
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
|
* @since [v6.0]
|
||||||
|
* @author [T. Scarsbrook] [<snipe@scarzybrook.co.uk>]
|
||||||
|
*/
|
||||||
|
public function store(UploadFileRequest $request, $assetId = null)
|
||||||
|
{
|
||||||
|
// Start by checking if the asset being acted upon exists
|
||||||
|
if (! $asset = Asset::find($assetId)) {
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we are allowed to update this asset
|
||||||
|
$this->authorize('update', $asset);
|
||||||
|
|
||||||
|
if ($request->hasFile('file')) {
|
||||||
|
// If the file storage directory doesn't exist; create it
|
||||||
|
if (! Storage::exists('private_uploads/assets')) {
|
||||||
|
Storage::makeDirectory('private_uploads/assets', 775);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop over the attached files and add them to the asset
|
||||||
|
foreach ($request->file('file') as $file) {
|
||||||
|
$file_name = $request->handleFile('private_uploads/assets/','hardware-'.$asset->id, $file);
|
||||||
|
|
||||||
|
$asset->logUpload($file_name, e($request->get('notes')));
|
||||||
|
}
|
||||||
|
|
||||||
|
// All done - report success
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/message.upload.success')));
|
||||||
|
}
|
||||||
|
|
||||||
|
// We only reach here if no files were included in the POST, so tell the user this
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.upload.nofiles')), 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List the files for an asset.
|
||||||
|
*
|
||||||
|
* @param int $assetId
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
|
* @since [v6.0]
|
||||||
|
* @author [T. Scarsbrook] [<snipe@scarzybrook.co.uk>]
|
||||||
|
*/
|
||||||
|
public function list($assetId = null)
|
||||||
|
{
|
||||||
|
// Start by checking if the asset being acted upon exists
|
||||||
|
if (! $asset = Asset::find($assetId)) {
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
// the asset is valid
|
||||||
|
if (isset($asset->id)) {
|
||||||
|
$this->authorize('view', $asset);
|
||||||
|
|
||||||
|
// Check that there are some uploads on this asset that can be listed
|
||||||
|
if ($asset->uploads->count() > 0) {
|
||||||
|
$files = array();
|
||||||
|
foreach ($asset->uploads as $upload) {
|
||||||
|
array_push($files, $upload);
|
||||||
|
}
|
||||||
|
// Give the list of files back to the user
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('success', $files, trans('admin/hardware/message.upload.success')));
|
||||||
|
}
|
||||||
|
|
||||||
|
// There are no files.
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('success', array(), trans('admin/hardware/message.upload.success')));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send back an error message
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.download.error')), 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check for permissions and display the file.
|
||||||
|
*
|
||||||
|
* @param int $assetId
|
||||||
|
* @param int $fileId
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
|
* @since [v6.0]
|
||||||
|
* @author [T. Scarsbrook] [<snipe@scarzybrook.co.uk>]
|
||||||
|
*/
|
||||||
|
public function show($assetId = null, $fileId = null)
|
||||||
|
{
|
||||||
|
// Start by checking if the asset being acted upon exists
|
||||||
|
if (! $asset = Asset::find($assetId)) {
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
// the asset is valid
|
||||||
|
if (isset($asset->id)) {
|
||||||
|
$this->authorize('view', $asset);
|
||||||
|
|
||||||
|
// Check that the file being requested exists for the asset
|
||||||
|
if (! $log = Actionlog::whereNotNull('filename')->where('item_id', $asset->id)->find($fileId)) {
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.download.no_match', ['id' => $fileId])), 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Form the full filename with path
|
||||||
|
$file = 'private_uploads/assets/'.$log->filename;
|
||||||
|
\Log::debug('Checking for '.$file);
|
||||||
|
|
||||||
|
if ($log->action_type == 'audit') {
|
||||||
|
$file = 'private_uploads/audits/'.$log->filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the file actually exists on the filesystem
|
||||||
|
if (! Storage::exists($file)) {
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.download.does_not_exist', ['id' => $fileId])), 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request('inline') == 'true') {
|
||||||
|
|
||||||
|
$headers = [
|
||||||
|
'Content-Disposition' => 'inline',
|
||||||
|
];
|
||||||
|
|
||||||
|
return Storage::download($file, $log->filename, $headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
return StorageHelper::downloader($file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send back an error message
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.download.error', ['id' => $fileId])), 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete the associated file
|
||||||
|
*
|
||||||
|
* @param int $assetId
|
||||||
|
* @param int $fileId
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
|
* @since [v6.0]
|
||||||
|
* @author [T. Scarsbrook] [<snipe@scarzybrook.co.uk>]
|
||||||
|
*/
|
||||||
|
public function destroy($assetId = null, $fileId = null)
|
||||||
|
{
|
||||||
|
// Start by checking if the asset being acted upon exists
|
||||||
|
if (! $asset = Asset::find($assetId)) {
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
$rel_path = 'private_uploads/assets';
|
||||||
|
|
||||||
|
// the asset is valid
|
||||||
|
if (isset($asset->id)) {
|
||||||
|
$this->authorize('update', $asset);
|
||||||
|
|
||||||
|
// Check for the file
|
||||||
|
$log = Actionlog::find($fileId);
|
||||||
|
if ($log) {
|
||||||
|
// Check the file actually exists, and delete it
|
||||||
|
if (Storage::exists($rel_path.'/'.$log->filename)) {
|
||||||
|
Storage::delete($rel_path.'/'.$log->filename);
|
||||||
|
}
|
||||||
|
// Delete the record of the file
|
||||||
|
$log->delete();
|
||||||
|
|
||||||
|
// All deleting done - notify the user of success
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/hardware/message.deletefile.success')), 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The file doesn't seem to really exist, so report an error
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.deletefile.error')), 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.deletefile.error')), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,7 +8,7 @@ use App\Http\Transformers\AssetMaintenancesTransformer;
|
|||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use App\Models\AssetMaintenance;
|
use App\Models\AssetMaintenance;
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
use Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Input;
|
use Illuminate\Support\Facades\Input;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ use App\Models\AssetModel;
|
|||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Http\Requests\ImageUploadRequest;
|
use App\Http\Requests\ImageUploadRequest;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class controls all actions related to asset models for
|
* This class controls all actions related to asset models for
|
||||||
@@ -224,7 +225,7 @@ class AssetModelsController extends Controller
|
|||||||
try {
|
try {
|
||||||
Storage::disk('public')->delete('assetmodels/'.$assetmodel->image);
|
Storage::disk('public')->delete('assetmodels/'.$assetmodel->image);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
\Log::info($e);
|
Log::info($e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,17 +27,16 @@ use App\Models\Setting;
|
|||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use \Illuminate\Support\Facades\Auth;
|
use \Illuminate\Support\Facades\Auth;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Http\Requests\ImageUploadRequest;
|
use App\Http\Requests\ImageUploadRequest;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Input;
|
|
||||||
use Paginator;
|
use Paginator;
|
||||||
use Slack;
|
use Slack;
|
||||||
use Str;
|
use Str;
|
||||||
use TCPDF;
|
use TCPDF;
|
||||||
use Validator;
|
use Validator;
|
||||||
use Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -59,7 +58,7 @@ class AssetsController extends Controller
|
|||||||
* @since [v4.0]
|
* @since [v4.0]
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function index(Request $request, $audit = null)
|
public function index(Request $request, $action = null, $upcoming_status = null)
|
||||||
{
|
{
|
||||||
|
|
||||||
$filter_non_deprecable_assets = false;
|
$filter_non_deprecable_assets = false;
|
||||||
@@ -94,6 +93,7 @@ class AssetsController extends Controller
|
|||||||
'serial',
|
'serial',
|
||||||
'model_number',
|
'model_number',
|
||||||
'last_checkout',
|
'last_checkout',
|
||||||
|
'last_checkin',
|
||||||
'notes',
|
'notes',
|
||||||
'expected_checkin',
|
'expected_checkin',
|
||||||
'order_number',
|
'order_number',
|
||||||
@@ -154,17 +154,44 @@ class AssetsController extends Controller
|
|||||||
$assets->TextSearch($request->input('search'));
|
$assets->TextSearch($request->input('search'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is used by the audit reporting routes
|
|
||||||
if (Gate::allows('audit', Asset::class)) {
|
/**
|
||||||
switch ($audit) {
|
* Handle due and overdue audits and checkin dates
|
||||||
case 'due':
|
*/
|
||||||
$assets->DueOrOverdueForAudit($settings);
|
switch ($action) {
|
||||||
break;
|
case 'audits':
|
||||||
case 'overdue':
|
|
||||||
$assets->overdueForAudit($settings);
|
switch ($upcoming_status) {
|
||||||
break;
|
case 'due':
|
||||||
|
$assets->DueForAudit($settings);
|
||||||
|
break;
|
||||||
|
case 'overdue':
|
||||||
|
$assets->OverdueForAudit();
|
||||||
|
break;
|
||||||
|
case 'due-or-overdue':
|
||||||
|
$assets->DueOrOverdueForAudit($settings);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'checkins':
|
||||||
|
switch ($upcoming_status) {
|
||||||
|
case 'due':
|
||||||
|
$assets->DueForCheckin($settings);
|
||||||
|
break;
|
||||||
|
case 'overdue':
|
||||||
|
$assets->OverdueForCheckin();
|
||||||
|
break;
|
||||||
|
case 'due-or-overdue':
|
||||||
|
$assets->DueOrOverdueForCheckin($settings);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* End handling due and overdue audits and checkin dates
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
// This is used by the sidenav, mostly
|
// This is used by the sidenav, mostly
|
||||||
@@ -558,44 +585,8 @@ class AssetsController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
$asset = $request->handleImages($asset);
|
$asset = $request->handleImages($asset);
|
||||||
|
$asset = $asset->handleCustomFieldsForStoring($request);
|
||||||
|
|
||||||
// Update custom fields in the database.
|
|
||||||
$model = AssetModel::find($request->input('model_id'));
|
|
||||||
|
|
||||||
// Check that it's an object and not a collection
|
|
||||||
// (Sometimes people send arrays here and they shouldn't
|
|
||||||
if (($model) && ($model instanceof AssetModel) && ($model->fieldset)) {
|
|
||||||
foreach ($model->fieldset->fields as $field) {
|
|
||||||
|
|
||||||
// Set the field value based on what was sent in the request
|
|
||||||
$field_val = $request->input($field->db_column, null);
|
|
||||||
|
|
||||||
// If input value is null, use custom field's default value
|
|
||||||
if ($field_val == null) {
|
|
||||||
Log::debug('Field value for '.$field->db_column.' is null');
|
|
||||||
$field_val = $field->defaultValue($request->get('model_id'));
|
|
||||||
Log::debug('Use the default fieldset value of '.$field->defaultValue($request->get('model_id')));
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the field is set to encrypted, make sure we encrypt the value
|
|
||||||
if ($field->field_encrypted == '1') {
|
|
||||||
Log::debug('This model field is encrypted in this fieldset.');
|
|
||||||
|
|
||||||
if (Gate::allows('admin')) {
|
|
||||||
|
|
||||||
// If input value is null, use custom field's default value
|
|
||||||
if (($field_val == null) && ($request->has('model_id') != '')) {
|
|
||||||
$field_val = Crypt::encrypt($field->defaultValue($request->get('model_id')));
|
|
||||||
} else {
|
|
||||||
$field_val = Crypt::encrypt($request->input($field->db_column));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$asset->{$field->db_column} = $field_val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($asset->save()) {
|
if ($asset->save()) {
|
||||||
if ($request->get('assigned_user')) {
|
if ($request->get('assigned_user')) {
|
||||||
@@ -614,6 +605,8 @@ class AssetsController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/message.create.success')));
|
return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/message.create.success')));
|
||||||
|
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('success', (new AssetsTransformer)->transformAsset($asset), trans('admin/hardware/message.create.success')));
|
||||||
}
|
}
|
||||||
|
|
||||||
return response()->json(Helper::formatStandardApiResponse('error', null, $asset->getErrors()), 200);
|
return response()->json(Helper::formatStandardApiResponse('error', null, $asset->getErrors()), 200);
|
||||||
@@ -654,22 +647,7 @@ class AssetsController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
$asset = $request->handleImages($asset);
|
$asset = $request->handleImages($asset);
|
||||||
$model = AssetModel::find($asset->model_id);
|
$asset = $asset->handleCustomFieldsForStoring($request);
|
||||||
|
|
||||||
// Update custom fields
|
|
||||||
if (($model) && (isset($model->fieldset))) {
|
|
||||||
foreach ($model->fieldset->fields as $field) {
|
|
||||||
if ($request->has($field->db_column)) {
|
|
||||||
if ($field->field_encrypted == '1') {
|
|
||||||
if (Gate::allows('admin')) {
|
|
||||||
$asset->{$field->db_column} = \Crypt::encrypt($request->input($field->db_column));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$asset->{$field->db_column} = $request->input($field->db_column);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if ($asset->save()) {
|
if ($asset->save()) {
|
||||||
@@ -692,7 +670,11 @@ class AssetsController extends Controller
|
|||||||
$asset->image = $asset->getImageUrl();
|
$asset->image = $asset->getImageUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/message.update.success')));
|
if ($problems_updating_encrypted_custom_fields) {
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/message.update.encrypted_warning')));
|
||||||
|
} else {
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/message.update.success')));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return response()->json(Helper::formatStandardApiResponse('error', null, $asset->getErrors()), 200);
|
return response()->json(Helper::formatStandardApiResponse('error', null, $asset->getErrors()), 200);
|
||||||
@@ -802,7 +784,6 @@ class AssetsController extends Controller
|
|||||||
'asset_tag' => $asset->asset_tag,
|
'asset_tag' => $asset->asset_tag,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
// This item is checked out to a location
|
// This item is checked out to a location
|
||||||
if (request('checkout_to_type') == 'location') {
|
if (request('checkout_to_type') == 'location') {
|
||||||
$target = Location::find(request('assigned_location'));
|
$target = Location::find(request('assigned_location'));
|
||||||
@@ -829,13 +810,10 @@ class AssetsController extends Controller
|
|||||||
$asset->status_id = $request->get('status_id');
|
$asset->status_id = $request->get('status_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (! isset($target)) {
|
if (! isset($target)) {
|
||||||
return response()->json(Helper::formatStandardApiResponse('error', $error_payload, 'Checkout target for asset '.e($asset->asset_tag).' is invalid - '.$error_payload['target_type'].' does not exist.'));
|
return response()->json(Helper::formatStandardApiResponse('error', $error_payload, 'Checkout target for asset '.e($asset->asset_tag).' is invalid - '.$error_payload['target_type'].' does not exist.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$checkout_at = request('checkout_at', date('Y-m-d H:i:s'));
|
$checkout_at = request('checkout_at', date('Y-m-d H:i:s'));
|
||||||
$expected_checkin = request('expected_checkin', null);
|
$expected_checkin = request('expected_checkin', null);
|
||||||
$note = request('note', null);
|
$note = request('note', null);
|
||||||
@@ -851,8 +829,6 @@ class AssetsController extends Controller
|
|||||||
// $asset->location_id = $target->rtd_location_id;
|
// $asset->location_id = $target->rtd_location_id;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if ($asset->checkOut($target, Auth::user(), $checkout_at, $expected_checkin, $note, $asset_name, $asset->location_id)) {
|
if ($asset->checkOut($target, Auth::user(), $checkout_at, $expected_checkin, $note, $asset_name, $asset->location_id)) {
|
||||||
return response()->json(Helper::formatStandardApiResponse('success', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.checkout.success')));
|
return response()->json(Helper::formatStandardApiResponse('success', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.checkout.success')));
|
||||||
}
|
}
|
||||||
@@ -983,25 +959,39 @@ class AssetsController extends Controller
|
|||||||
|
|
||||||
{
|
{
|
||||||
$this->authorize('audit', Asset::class);
|
$this->authorize('audit', Asset::class);
|
||||||
$rules = [
|
|
||||||
'asset_tag' => 'required',
|
|
||||||
'location_id' => 'exists:locations,id|nullable|numeric',
|
|
||||||
'next_audit_date' => 'date|nullable',
|
|
||||||
];
|
|
||||||
|
|
||||||
$validator = Validator::make($request->all(), $rules);
|
|
||||||
if ($validator->fails()) {
|
|
||||||
return response()->json(Helper::formatStandardApiResponse('error', null, $validator->errors()->all()));
|
|
||||||
}
|
|
||||||
|
|
||||||
$settings = Setting::getSettings();
|
$settings = Setting::getSettings();
|
||||||
$dt = Carbon::now()->addMonths($settings->audit_interval)->toDateString();
|
$dt = Carbon::now()->addMonths($settings->audit_interval)->toDateString();
|
||||||
|
|
||||||
|
// No tag passed - return an error
|
||||||
|
if (!$request->filled('asset_tag')) {
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('error', [
|
||||||
|
'asset_tag'=> '',
|
||||||
|
'error'=> trans('admin/hardware/message.no_tag'),
|
||||||
|
], trans('admin/hardware/message.no_tag')), 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$asset = Asset::where('asset_tag', '=', $request->input('asset_tag'))->first();
|
$asset = Asset::where('asset_tag', '=', $request->input('asset_tag'))->first();
|
||||||
|
|
||||||
|
|
||||||
if ($asset) {
|
if ($asset) {
|
||||||
// We don't want to log this as a normal update, so let's bypass that
|
|
||||||
|
/**
|
||||||
|
* Even though we do a save() further down, we don't want to log this as a "normal" asset update,
|
||||||
|
* which would trigger the Asset Observer and would log an asset *update* log entry (because the
|
||||||
|
* de-normed fields like next_audit_date on the asset itself will change on save()) *in addition* to
|
||||||
|
* the audit log entry we're creating through this controller.
|
||||||
|
*
|
||||||
|
* To prevent this double-logging (one for update and one for audit), we skip the observer and bypass
|
||||||
|
* that de-normed update log entry by using unsetEventDispatcher(), BUT invoking unsetEventDispatcher()
|
||||||
|
* will bypass normal model-level validation that's usually handled at the observer )
|
||||||
|
*
|
||||||
|
* We handle validation on the save() by checking if the asset is valid via the ->isValid() method,
|
||||||
|
* which manually invokes Watson Validating to make sure the asset's model is valid.
|
||||||
|
*
|
||||||
|
* @see \App\Observers\AssetObserver::updating()
|
||||||
|
*/
|
||||||
$asset->unsetEventDispatcher();
|
$asset->unsetEventDispatcher();
|
||||||
$asset->next_audit_date = $dt;
|
$asset->next_audit_date = $dt;
|
||||||
|
|
||||||
@@ -1017,8 +1007,12 @@ class AssetsController extends Controller
|
|||||||
|
|
||||||
$asset->last_audit_date = date('Y-m-d H:i:s');
|
$asset->last_audit_date = date('Y-m-d H:i:s');
|
||||||
|
|
||||||
if ($asset->save()) {
|
/**
|
||||||
$log = $asset->logAudit(request('note'), request('location_id'));
|
* Invoke Watson Validating to check the asset itself and check to make sure it saved correctly.
|
||||||
|
* We have to invoke this manually because of the unsetEventDispatcher() above.)
|
||||||
|
*/
|
||||||
|
if ($asset->isValid() && $asset->save()) {
|
||||||
|
$asset->logAudit(request('note'), request('location_id'));
|
||||||
|
|
||||||
return response()->json(Helper::formatStandardApiResponse('success', [
|
return response()->json(Helper::formatStandardApiResponse('success', [
|
||||||
'asset_tag'=> e($asset->asset_tag),
|
'asset_tag'=> e($asset->asset_tag),
|
||||||
@@ -1026,9 +1020,23 @@ class AssetsController extends Controller
|
|||||||
'next_audit_date' => Helper::getFormattedDateObject($asset->next_audit_date),
|
'next_audit_date' => Helper::getFormattedDateObject($asset->next_audit_date),
|
||||||
], trans('admin/hardware/message.audit.success')));
|
], trans('admin/hardware/message.audit.success')));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Asset failed validation or was not able to be saved
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('error', [
|
||||||
|
'asset_tag'=> e($asset->asset_tag),
|
||||||
|
'error'=> $asset->getErrors()->first(),
|
||||||
|
], trans('admin/hardware/message.audit.error', ['error' => $asset->getErrors()->first()])), 200);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return response()->json(Helper::formatStandardApiResponse('error', ['asset_tag'=> e($request->input('asset_tag'))], 'Asset with tag '.e($request->input('asset_tag')).' not found'));
|
|
||||||
|
// No matching asset for the asset tag that was passed.
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('error', [
|
||||||
|
'asset_tag'=> e($request->input('asset_tag')),
|
||||||
|
'error'=> trans('admin/hardware/message.audit.error'),
|
||||||
|
], trans('admin/hardware/message.audit.error', ['error' => trans('admin/hardware/message.does_not_exist')])), 200);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1062,8 +1070,7 @@ class AssetsController extends Controller
|
|||||||
|
|
||||||
$assets = Asset::select('assets.*')
|
$assets = Asset::select('assets.*')
|
||||||
->with('location', 'assetstatus', 'assetlog', 'company','assignedTo',
|
->with('location', 'assetstatus', 'assetlog', 'company','assignedTo',
|
||||||
'model.category', 'model.manufacturer', 'model.fieldset', 'supplier', 'requests')
|
'model.category', 'model.manufacturer', 'model.fieldset', 'supplier', 'requests');
|
||||||
->requestableAssets();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1071,7 +1078,7 @@ class AssetsController extends Controller
|
|||||||
if ($request->filled('search')) {
|
if ($request->filled('search')) {
|
||||||
$assets->TextSearch($request->input('search'));
|
$assets->TextSearch($request->input('search'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search custom fields by column name
|
// Search custom fields by column name
|
||||||
foreach ($all_custom_fields as $field) {
|
foreach ($all_custom_fields as $field) {
|
||||||
if ($request->filled($field->db_column_name())) {
|
if ($request->filled($field->db_column_name())) {
|
||||||
@@ -1101,6 +1108,7 @@ class AssetsController extends Controller
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$assets->requestableAssets();
|
||||||
|
|
||||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||||
$offset = ($request->input('offset') > $assets->count()) ? $assets->count() : app('api_offset_value');
|
$offset = ($request->input('offset') > $assets->count()) ? $assets->count() : app('api_offset_value');
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ use App\Events\ComponentCheckedIn;
|
|||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Illuminate\Database\Query\Builder;
|
use Illuminate\Database\Query\Builder;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class ComponentsController extends Controller
|
class ComponentsController extends Controller
|
||||||
{
|
{
|
||||||
@@ -331,7 +332,7 @@ class ComponentsController extends Controller
|
|||||||
// actually checked out.
|
// actually checked out.
|
||||||
$component_assets->assigned_qty = $qty_remaining_in_checkout;
|
$component_assets->assigned_qty = $qty_remaining_in_checkout;
|
||||||
|
|
||||||
\Log::debug($component_asset_id.' - '.$qty_remaining_in_checkout.' remaining in record '.$component_assets->id);
|
Log::debug($component_asset_id.' - '.$qty_remaining_in_checkout.' remaining in record '.$component_assets->id);
|
||||||
|
|
||||||
\DB::table('components_assets')->where('id',
|
\DB::table('components_assets')->where('id',
|
||||||
$component_asset_id)->update(['assigned_qty' => $qty_remaining_in_checkout]);
|
$component_asset_id)->update(['assigned_qty' => $qty_remaining_in_checkout]);
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ use App\Models\User;
|
|||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Http\Requests\ImageUploadRequest;
|
use App\Http\Requests\ImageUploadRequest;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class ConsumablesController extends Controller
|
class ConsumablesController extends Controller
|
||||||
{
|
{
|
||||||
@@ -277,7 +278,7 @@ class ConsumablesController extends Controller
|
|||||||
if (!$user = User::find($request->input('assigned_to'))) {
|
if (!$user = User::find($request->input('assigned_to'))) {
|
||||||
// Return error message
|
// Return error message
|
||||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'No user found'));
|
return response()->json(Helper::formatStandardApiResponse('error', null, 'No user found'));
|
||||||
\Log::debug('No valid user');
|
Log::debug('No valid user');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the consumable data
|
// Update the consumable data
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ class CustomFieldsController extends Controller
|
|||||||
*
|
*
|
||||||
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
|
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
|
||||||
* @since [v1.8]
|
* @since [v1.8]
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function destroy($field_id)
|
public function destroy($field_id)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ class CustomFieldsetsController extends Controller
|
|||||||
*
|
*
|
||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @since [v4.0]
|
* @since [v4.0]
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function destroy($id)
|
public function destroy($id)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use App\Http\Transformers\DepartmentsTransformer;
|
|||||||
use App\Http\Transformers\SelectlistTransformer;
|
use App\Http\Transformers\SelectlistTransformer;
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
use App\Models\Department;
|
use App\Models\Department;
|
||||||
use Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Http\Requests\ImageUploadRequest;
|
use App\Http\Requests\ImageUploadRequest;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use App\Http\Controllers\Controller;
|
|||||||
use App\Http\Transformers\GroupsTransformer;
|
use App\Http\Transformers\GroupsTransformer;
|
||||||
use App\Models\Group;
|
use App\Models\Group;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
|
|
||||||
class GroupsController extends Controller
|
class GroupsController extends Controller
|
||||||
@@ -62,13 +62,16 @@ class GroupsController extends Controller
|
|||||||
{
|
{
|
||||||
$this->authorize('superadmin');
|
$this->authorize('superadmin');
|
||||||
$group = new Group;
|
$group = new Group;
|
||||||
|
// Get all the available permissions
|
||||||
|
$permissions = config('permissions');
|
||||||
|
$groupPermissions = Helper::selectedPermissionsArray($permissions, $permissions);
|
||||||
|
|
||||||
$group->name = $request->input('name');
|
$group->name = $request->input('name');
|
||||||
$group->created_by = Auth::user()->id;
|
$group->created_by = Auth::user()->id;
|
||||||
$group->permissions = json_encode($request->input('permissions')); // Todo - some JSON validation stuff here
|
$group->permissions = json_encode($request->input('permissions', $groupPermissions));
|
||||||
|
|
||||||
if ($group->save()) {
|
if ($group->save()) {
|
||||||
return response()->json(Helper::formatStandardApiResponse('success', $group, trans('admin/groups/message.create.success')));
|
return response()->json(Helper::formatStandardApiResponse('success', (new GroupsTransformer)->transformGroup($group), trans('admin/groups/message.success.create')));
|
||||||
}
|
}
|
||||||
|
|
||||||
return response()->json(Helper::formatStandardApiResponse('error', null, $group->getErrors()));
|
return response()->json(Helper::formatStandardApiResponse('error', null, $group->getErrors()));
|
||||||
@@ -86,7 +89,6 @@ class GroupsController extends Controller
|
|||||||
{
|
{
|
||||||
$this->authorize('superadmin');
|
$this->authorize('superadmin');
|
||||||
$group = Group::findOrFail($id);
|
$group = Group::findOrFail($id);
|
||||||
|
|
||||||
return (new GroupsTransformer)->transformGroup($group);
|
return (new GroupsTransformer)->transformGroup($group);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,7 +110,7 @@ class GroupsController extends Controller
|
|||||||
$group->permissions = $request->input('permissions'); // Todo - some JSON validation stuff here
|
$group->permissions = $request->input('permissions'); // Todo - some JSON validation stuff here
|
||||||
|
|
||||||
if ($group->save()) {
|
if ($group->save()) {
|
||||||
return response()->json(Helper::formatStandardApiResponse('success', $group, trans('admin/groups/message.update.success')));
|
return response()->json(Helper::formatStandardApiResponse('success', (new GroupsTransformer)->transformGroup($group), trans('admin/groups/message.success.update')));
|
||||||
}
|
}
|
||||||
|
|
||||||
return response()->json(Helper::formatStandardApiResponse('error', null, $group->getErrors()));
|
return response()->json(Helper::formatStandardApiResponse('error', null, $group->getErrors()));
|
||||||
|
|||||||
@@ -9,13 +9,14 @@ use App\Http\Transformers\ImportsTransformer;
|
|||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
use App\Models\Import;
|
use App\Models\Import;
|
||||||
use Artisan;
|
use Illuminate\Support\Facades\Artisan;
|
||||||
use Illuminate\Database\Eloquent\JsonEncodingException;
|
use Illuminate\Database\Eloquent\JsonEncodingException;
|
||||||
use Illuminate\Support\Facades\Request;
|
use Illuminate\Support\Facades\Request;
|
||||||
use Illuminate\Support\Facades\Session;
|
use Illuminate\Support\Facades\Session;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use League\Csv\Reader;
|
use League\Csv\Reader;
|
||||||
use Symfony\Component\HttpFoundation\File\Exception\FileException;
|
use Symfony\Component\HttpFoundation\File\Exception\FileException;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class ImportController extends Controller
|
class ImportController extends Controller
|
||||||
{
|
{
|
||||||
@@ -159,10 +160,10 @@ class ImportController extends Controller
|
|||||||
|
|
||||||
// Run a backup immediately before processing
|
// Run a backup immediately before processing
|
||||||
if ($request->get('run-backup')) {
|
if ($request->get('run-backup')) {
|
||||||
\Log::debug('Backup manually requested via importer');
|
Log::debug('Backup manually requested via importer');
|
||||||
Artisan::call('snipeit:backup', ['--filename' => 'pre-import-backup-'.date('Y-m-d-H:i:s')]);
|
Artisan::call('snipeit:backup', ['--filename' => 'pre-import-backup-'.date('Y-m-d-H:i:s')]);
|
||||||
} else {
|
} else {
|
||||||
\Log::debug('NO BACKUP requested via importer');
|
Log::debug('NO BACKUP requested via importer');
|
||||||
}
|
}
|
||||||
|
|
||||||
$import = Import::find($import_id);
|
$import = Import::find($import_id);
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use App\Http\Transformers\LabelsTransformer;
|
|||||||
use App\Models\Labels\Label;
|
use App\Models\Labels\Label;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\ItemNotFoundException;
|
use Illuminate\Support\ItemNotFoundException;
|
||||||
use Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
class LabelsController extends Controller
|
class LabelsController extends Controller
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use App\Models\Asset;
|
|||||||
use App\Models\License;
|
use App\Models\License;
|
||||||
use App\Models\LicenseSeat;
|
use App\Models\LicenseSeat;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
class LicenseSeatsController extends Controller
|
class LicenseSeatsController extends Controller
|
||||||
|
|||||||
@@ -235,10 +235,16 @@ class LocationsController extends Controller
|
|||||||
public function destroy($id)
|
public function destroy($id)
|
||||||
{
|
{
|
||||||
$this->authorize('delete', Location::class);
|
$this->authorize('delete', Location::class);
|
||||||
$location = Location::findOrFail($id);
|
$location = Location::withCount('assignedAssets as assigned_assets_count')
|
||||||
|
->withCount('assets as assets_count')
|
||||||
|
->withCount('rtd_assets as rtd_assets_count')
|
||||||
|
->withCount('children as children_count')
|
||||||
|
->withCount('users as users_count')
|
||||||
|
->findOrFail($id);
|
||||||
|
|
||||||
if (! $location->isDeletable()) {
|
if (! $location->isDeletable()) {
|
||||||
return response()
|
return response()
|
||||||
->json(Helper::formatStandardApiResponse('error', null, trans('admin/companies/message.assoc_users')));
|
->json(Helper::formatStandardApiResponse('error', null, trans('admin/locations/message.assoc_users')));
|
||||||
}
|
}
|
||||||
$this->authorize('delete', $location);
|
$this->authorize('delete', $location);
|
||||||
$location->delete();
|
$location->delete();
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use Laravel\Passport\TokenRepository;
|
|||||||
use Illuminate\Contracts\Validation\Factory as ValidationFactory;
|
use Illuminate\Contracts\Validation\Factory as ValidationFactory;
|
||||||
use Illuminate\Support\Facades\Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use App\Models\CustomField;
|
use App\Models\CustomField;
|
||||||
use DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
class ProfileController extends Controller
|
class ProfileController extends Controller
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -32,19 +32,26 @@ class ReportsController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (($request->filled('item_type')) && ($request->filled('item_id'))) {
|
if (($request->filled('item_type')) && ($request->filled('item_id'))) {
|
||||||
$actionlogs = $actionlogs->where('item_id', '=', $request->input('item_id'))
|
$actionlogs = $actionlogs->where(function($query) use ($request)
|
||||||
|
{
|
||||||
|
$query->where('item_id', '=', $request->input('item_id'))
|
||||||
->where('item_type', '=', 'App\\Models\\'.ucwords($request->input('item_type')))
|
->where('item_type', '=', 'App\\Models\\'.ucwords($request->input('item_type')))
|
||||||
->orWhere(function($query) use ($request)
|
->orWhere(function($query) use ($request)
|
||||||
{
|
{
|
||||||
$query->where('target_id', '=', $request->input('item_id'))
|
$query->where('target_id', '=', $request->input('item_id'))
|
||||||
->where('target_type', '=', 'App\\Models\\'.ucwords($request->input('item_type')));
|
->where('target_type', '=', 'App\\Models\\'.ucwords($request->input('item_type')));
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->filled('action_type')) {
|
if ($request->filled('action_type')) {
|
||||||
$actionlogs = $actionlogs->where('action_type', '=', $request->input('action_type'))->orderBy('created_at', 'desc');
|
$actionlogs = $actionlogs->where('action_type', '=', $request->input('action_type'))->orderBy('created_at', 'desc');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($request->filled('user_id')) {
|
||||||
|
$actionlogs = $actionlogs->where('user_id', '=', $request->input('user_id'));
|
||||||
|
}
|
||||||
|
|
||||||
if ($request->filled('action_source')) {
|
if ($request->filled('action_source')) {
|
||||||
$actionlogs = $actionlogs->where('action_source', '=', $request->input('action_source'))->orderBy('created_at', 'desc');
|
$actionlogs = $actionlogs->where('action_source', '=', $request->input('action_source'))->orderBy('created_at', 'desc');
|
||||||
}
|
}
|
||||||
@@ -71,13 +78,14 @@ class ReportsController extends Controller
|
|||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
$total = $actionlogs->count();
|
||||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||||
$offset = ($request->input('offset') > $actionlogs->count()) ? $actionlogs->count() : app('api_offset_value');
|
$offset = ($request->input('offset') > $total) ? $total : app('api_offset_value');
|
||||||
$limit = app('api_limit_value');
|
$limit = app('api_limit_value');
|
||||||
|
|
||||||
$sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
|
$sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
|
||||||
$order = ($request->input('order') == 'asc') ? 'asc' : 'desc';
|
$order = ($request->input('order') == 'asc') ? 'asc' : 'desc';
|
||||||
$total = $actionlogs->count();
|
|
||||||
|
|
||||||
$actionlogs = $actionlogs->orderBy($sort, $order)->skip($offset)->take($limit)->get();
|
$actionlogs = $actionlogs->orderBy($sort, $order)->skip($offset)->take($limit)->get();
|
||||||
|
|
||||||
|
|||||||
@@ -33,18 +33,18 @@ class SettingsController extends Controller
|
|||||||
$settings = Setting::getSettings();
|
$settings = Setting::getSettings();
|
||||||
|
|
||||||
if ($settings->ldap_enabled!='1') {
|
if ($settings->ldap_enabled!='1') {
|
||||||
\Log::debug('LDAP is not enabled cannot test.');
|
Log::debug('LDAP is not enabled cannot test.');
|
||||||
return response()->json(['message' => 'LDAP is not enabled, cannot test.'], 400);
|
return response()->json(['message' => 'LDAP is not enabled, cannot test.'], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
\Log::debug('Preparing to test LDAP connection');
|
Log::debug('Preparing to test LDAP connection');
|
||||||
|
|
||||||
$message = []; //where we collect together test messages
|
$message = []; //where we collect together test messages
|
||||||
try {
|
try {
|
||||||
$connection = Ldap::connectToLdap();
|
$connection = Ldap::connectToLdap();
|
||||||
try {
|
try {
|
||||||
$message['bind'] = ['message' => 'Successfully bound to LDAP server.'];
|
$message['bind'] = ['message' => 'Successfully bound to LDAP server.'];
|
||||||
\Log::debug('attempting to bind to LDAP for LDAP test');
|
Log::debug('attempting to bind to LDAP for LDAP test');
|
||||||
Ldap::bindAdminToLdap($connection);
|
Ldap::bindAdminToLdap($connection);
|
||||||
$message['login'] = [
|
$message['login'] = [
|
||||||
'message' => 'Successfully connected to LDAP server.',
|
'message' => 'Successfully connected to LDAP server.',
|
||||||
@@ -75,13 +75,13 @@ class SettingsController extends Controller
|
|||||||
|
|
||||||
return response()->json($message, 200);
|
return response()->json($message, 200);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
\Log::debug('Bind failed');
|
Log::debug('Bind failed');
|
||||||
\Log::debug("Exception was: ".$e->getMessage());
|
Log::debug("Exception was: ".$e->getMessage());
|
||||||
return response()->json(['message' => $e->getMessage()], 400);
|
return response()->json(['message' => $e->getMessage()], 400);
|
||||||
//return response()->json(['message' => $e->getMessage()], 500);
|
//return response()->json(['message' => $e->getMessage()], 500);
|
||||||
}
|
}
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
\Log::debug('Connection failed but we cannot debug it any further on our end.');
|
Log::debug('Connection failed but we cannot debug it any further on our end.');
|
||||||
return response()->json(['message' => $e->getMessage()], 500);
|
return response()->json(['message' => $e->getMessage()], 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ class SettingsController extends Controller
|
|||||||
{
|
{
|
||||||
|
|
||||||
if (Setting::getSettings()->ldap_enabled != '1') {
|
if (Setting::getSettings()->ldap_enabled != '1') {
|
||||||
\Log::debug('LDAP is not enabled. Cannot test.');
|
Log::debug('LDAP is not enabled. Cannot test.');
|
||||||
return response()->json(['message' => 'LDAP is not enabled, cannot test.'], 400);
|
return response()->json(['message' => 'LDAP is not enabled, cannot test.'], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,39 +104,39 @@ class SettingsController extends Controller
|
|||||||
|
|
||||||
$validator = Validator::make($request->all(), $rules);
|
$validator = Validator::make($request->all(), $rules);
|
||||||
if ($validator->fails()) {
|
if ($validator->fails()) {
|
||||||
\Log::debug('LDAP Validation test failed.');
|
Log::debug('LDAP Validation test failed.');
|
||||||
$validation_errors = implode(' ',$validator->errors()->all());
|
$validation_errors = implode(' ',$validator->errors()->all());
|
||||||
return response()->json(['message' => $validator->errors()->all()], 400);
|
return response()->json(['message' => $validator->errors()->all()], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
\Log::debug('Preparing to test LDAP login');
|
Log::debug('Preparing to test LDAP login');
|
||||||
try {
|
try {
|
||||||
$connection = Ldap::connectToLdap();
|
$connection = Ldap::connectToLdap();
|
||||||
try {
|
try {
|
||||||
Ldap::bindAdminToLdap($connection);
|
Ldap::bindAdminToLdap($connection);
|
||||||
\Log::debug('Attempting to bind to LDAP for LDAP test');
|
Log::debug('Attempting to bind to LDAP for LDAP test');
|
||||||
try {
|
try {
|
||||||
$ldap_user = Ldap::findAndBindUserLdap($request->input('ldaptest_user'), $request->input('ldaptest_password'));
|
$ldap_user = Ldap::findAndBindUserLdap($request->input('ldaptest_user'), $request->input('ldaptest_password'));
|
||||||
if ($ldap_user) {
|
if ($ldap_user) {
|
||||||
\Log::debug('It worked! '. $request->input('ldaptest_user').' successfully binded to LDAP.');
|
Log::debug('It worked! '. $request->input('ldaptest_user').' successfully binded to LDAP.');
|
||||||
return response()->json(['message' => 'It worked! '. $request->input('ldaptest_user').' successfully binded to LDAP.'], 200);
|
return response()->json(['message' => 'It worked! '. $request->input('ldaptest_user').' successfully binded to LDAP.'], 200);
|
||||||
}
|
}
|
||||||
return response()->json(['message' => 'Login Failed. '. $request->input('ldaptest_user').' did not successfully bind to LDAP.'], 400);
|
return response()->json(['message' => 'Login Failed. '. $request->input('ldaptest_user').' did not successfully bind to LDAP.'], 400);
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
\Log::debug('LDAP login failed');
|
Log::debug('LDAP login failed');
|
||||||
return response()->json(['message' => $e->getMessage()], 400);
|
return response()->json(['message' => $e->getMessage()], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
\Log::debug('Bind failed');
|
Log::debug('Bind failed');
|
||||||
return response()->json(['message' => $e->getMessage()], 400);
|
return response()->json(['message' => $e->getMessage()], 400);
|
||||||
//return response()->json(['message' => $e->getMessage()], 500);
|
//return response()->json(['message' => $e->getMessage()], 500);
|
||||||
}
|
}
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
\Log::debug('Connection failed');
|
Log::debug('Connection failed');
|
||||||
return response()->json(['message' => $e->getMessage()], 500);
|
return response()->json(['message' => $e->getMessage()], 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,19 +181,19 @@ class SettingsController extends Controller
|
|||||||
|
|
||||||
$file_parts = explode('.', $file);
|
$file_parts = explode('.', $file);
|
||||||
$extension = end($file_parts);
|
$extension = end($file_parts);
|
||||||
\Log::debug($extension);
|
Log::debug($extension);
|
||||||
|
|
||||||
// Only generated barcodes would have a .png file extension
|
// Only generated barcodes would have a .png file extension
|
||||||
if ($extension == 'png') {
|
if ($extension == 'png') {
|
||||||
\Log::debug('Deleting: '.$file);
|
Log::debug('Deleting: '.$file);
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Storage::disk('public')->delete($file);
|
Storage::disk('public')->delete($file);
|
||||||
\Log::debug('Deleting: '.$file);
|
Log::debug('Deleting: '.$file);
|
||||||
$file_count++;
|
$file_count++;
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
\Log::debug($e);
|
Log::debug($e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,15 +13,17 @@ use App\Http\Transformers\SelectlistTransformer;
|
|||||||
use App\Http\Transformers\UsersTransformer;
|
use App\Http\Transformers\UsersTransformer;
|
||||||
use App\Models\Actionlog;
|
use App\Models\Actionlog;
|
||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use App\Models\Company;
|
use App\Models\Accessory;
|
||||||
|
use App\Models\Consumable;
|
||||||
use App\Models\License;
|
use App\Models\License;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Notifications\CurrentInventory;
|
use App\Notifications\CurrentInventory;
|
||||||
use Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Http\Requests\ImageUploadRequest;
|
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use App\Http\Requests\DeleteUserRequest;
|
||||||
|
|
||||||
class UsersController extends Controller
|
class UsersController extends Controller
|
||||||
{
|
{
|
||||||
@@ -31,7 +33,7 @@ class UsersController extends Controller
|
|||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @since [v4.0]
|
* @since [v4.0]
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\Response
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function index(Request $request)
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
@@ -75,10 +77,14 @@ class UsersController extends Controller
|
|||||||
'users.autoassign_licenses',
|
'users.autoassign_licenses',
|
||||||
'users.website',
|
'users.website',
|
||||||
|
|
||||||
])->with('manager', 'groups', 'userloc', 'company', 'department', 'assets', 'licenses', 'accessories', 'consumables', 'createdBy',)
|
])->with('manager', 'groups', 'userloc', 'company', 'department', 'assets', 'licenses', 'accessories', 'consumables', 'createdBy', 'managesUsers', 'managedLocations')
|
||||||
->withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count');
|
->withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count', 'managesUsers as manages_users_count', 'managedLocations as manages_locations_count');
|
||||||
|
|
||||||
|
|
||||||
|
if ($request->filled('search') != '') {
|
||||||
|
$users = $users->TextSearch($request->input('search'));
|
||||||
|
}
|
||||||
|
|
||||||
if ($request->filled('activated')) {
|
if ($request->filled('activated')) {
|
||||||
$users = $users->where('users.activated', '=', $request->input('activated'));
|
$users = $users->where('users.activated', '=', $request->input('activated'));
|
||||||
}
|
}
|
||||||
@@ -187,12 +193,23 @@ class UsersController extends Controller
|
|||||||
$users->has('accessories', '=', $request->input('accessories_count'));
|
$users->has('accessories', '=', $request->input('accessories_count'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($request->filled('manages_users_count')) {
|
||||||
|
$users->has('manages_users_count', '=', $request->input('manages_users_count'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->filled('manages_locations_count')) {
|
||||||
|
$users->has('manages_locations_count', '=', $request->input('manages_locations_count'));
|
||||||
|
}
|
||||||
|
|
||||||
if ($request->filled('autoassign_licenses')) {
|
if ($request->filled('autoassign_licenses')) {
|
||||||
$users->where('autoassign_licenses', '=', $request->input('autoassign_licenses'));
|
$users->where('autoassign_licenses', '=', $request->input('autoassign_licenses'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->filled('search')) {
|
|
||||||
$users = $users->TextSearch($request->input('search'));
|
if (($request->filled('deleted')) && ($request->input('deleted') == 'true')) {
|
||||||
|
$users = $users->onlyTrashed();
|
||||||
|
} elseif (($request->filled('all')) && ($request->input('all') == 'true')) {
|
||||||
|
$users = $users->withTrashed();
|
||||||
}
|
}
|
||||||
|
|
||||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||||
@@ -230,10 +247,6 @@ class UsersController extends Controller
|
|||||||
'jobtitle',
|
'jobtitle',
|
||||||
'username',
|
'username',
|
||||||
'employee_num',
|
'employee_num',
|
||||||
'assets',
|
|
||||||
'accessories',
|
|
||||||
'consumables',
|
|
||||||
'licenses',
|
|
||||||
'groups',
|
'groups',
|
||||||
'activated',
|
'activated',
|
||||||
'created_at',
|
'created_at',
|
||||||
@@ -244,6 +257,8 @@ class UsersController extends Controller
|
|||||||
'licenses_count',
|
'licenses_count',
|
||||||
'consumables_count',
|
'consumables_count',
|
||||||
'accessories_count',
|
'accessories_count',
|
||||||
|
'manages_users_count',
|
||||||
|
'manages_locations_count',
|
||||||
'phone',
|
'phone',
|
||||||
'address',
|
'address',
|
||||||
'city',
|
'city',
|
||||||
@@ -262,18 +277,11 @@ class UsersController extends Controller
|
|||||||
'website',
|
'website',
|
||||||
];
|
];
|
||||||
|
|
||||||
$sort = in_array($request->get('sort'), $allowed_columns) ? $request->get('sort') : 'first_name';
|
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'first_name';
|
||||||
$users = $users->orderBy($sort, $order);
|
$users = $users->orderBy($sort, $order);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($request->filled('deleted')) && ($request->input('deleted') == 'true')) {
|
|
||||||
$users = $users->onlyTrashed();
|
|
||||||
} elseif (($request->filled('all')) && ($request->input('all') == 'true')) {
|
|
||||||
$users = $users->withTrashed();
|
|
||||||
}
|
|
||||||
|
|
||||||
$users = Company::scopeCompanyables($users);
|
|
||||||
|
|
||||||
|
|
||||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||||
@@ -308,8 +316,6 @@ class UsersController extends Controller
|
|||||||
]
|
]
|
||||||
)->where('show_in_list', '=', '1');
|
)->where('show_in_list', '=', '1');
|
||||||
|
|
||||||
$users = Company::scopeCompanyables($users);
|
|
||||||
|
|
||||||
if ($request->filled('search')) {
|
if ($request->filled('search')) {
|
||||||
$users = $users->where(function ($query) use ($request) {
|
$users = $users->where(function ($query) use ($request) {
|
||||||
$query->SimpleNameSearch($request->get('search'))
|
$query->SimpleNameSearch($request->get('search'))
|
||||||
@@ -351,7 +357,7 @@ class UsersController extends Controller
|
|||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @since [v4.0]
|
* @since [v4.0]
|
||||||
* @param \Illuminate\Http\Request $request
|
* @param \Illuminate\Http\Request $request
|
||||||
* @return \Illuminate\Http\Response
|
* @return array | \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function store(SaveUserRequest $request)
|
public function store(SaveUserRequest $request)
|
||||||
{
|
{
|
||||||
@@ -398,14 +404,19 @@ class UsersController extends Controller
|
|||||||
*
|
*
|
||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @param int $id
|
* @param int $id
|
||||||
* @return \Illuminate\Http\Response
|
* @return array | \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function show($id)
|
public function show($id)
|
||||||
{
|
{
|
||||||
$this->authorize('view', User::class);
|
$this->authorize('view', User::class);
|
||||||
$user = User::withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count')->findOrFail($id);
|
|
||||||
|
|
||||||
return (new UsersTransformer)->transformUser($user);
|
if ($user = User::withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count', 'managesUsers as manages_users_count', 'managedLocations as manages_locations_count')->find($id)) {
|
||||||
|
$this->authorize('view', $user);
|
||||||
|
return (new UsersTransformer)->transformUser($user);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found', compact('id'))));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -416,89 +427,89 @@ class UsersController extends Controller
|
|||||||
* @since [v4.0]
|
* @since [v4.0]
|
||||||
* @param \Illuminate\Http\Request $request
|
* @param \Illuminate\Http\Request $request
|
||||||
* @param int $id
|
* @param int $id
|
||||||
* @return \Illuminate\Http\Response
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function update(SaveUserRequest $request, $id)
|
public function update(SaveUserRequest $request, $id)
|
||||||
{
|
{
|
||||||
$this->authorize('update', User::class);
|
$this->authorize('update', User::class);
|
||||||
|
|
||||||
$user = User::findOrFail($id);
|
if ($user = User::find($id)) {
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a janky hack to prevent people from changing admin demo user data on the public demo.
|
|
||||||
*
|
|
||||||
* The $ids 1 and 2 are special since they are seeded as superadmins in the demo seeder.
|
|
||||||
*
|
|
||||||
* Thanks, jerks. You are why we can't have nice things. - snipe
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
if ((($id == 1) || ($id == 2)) && (config('app.lock_passwords'))) {
|
$this->authorize('update', $user);
|
||||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'Permission denied. You cannot update user information via API on the demo.'));
|
|
||||||
}
|
/**
|
||||||
|
* This is a janky hack to prevent people from changing admin demo user data on the public demo.
|
||||||
|
* The $ids 1 and 2 are special since they are seeded as superadmins in the demo seeder.
|
||||||
|
* Thanks, jerks. You are why we can't have nice things. - snipe
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
$user->fill($request->all());
|
if ((($id == 1) || ($id == 2)) && (config('app.lock_passwords'))) {
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('error', null, 'Permission denied. You cannot update user information via API on the demo.'));
|
||||||
if ($user->id == $request->input('manager_id')) {
|
|
||||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot be your own manager'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($request->filled('password')) {
|
|
||||||
$user->password = bcrypt($request->input('password'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need to use has() instead of filled()
|
|
||||||
// here because we need to overwrite permissions
|
|
||||||
// if someone needs to null them out
|
|
||||||
if ($request->has('permissions')) {
|
|
||||||
$permissions_array = $request->input('permissions');
|
|
||||||
|
|
||||||
// Strip out the superuser permission if the API user isn't a superadmin
|
|
||||||
if (! Auth::user()->isSuperUser()) {
|
|
||||||
unset($permissions_array['superuser']);
|
|
||||||
}
|
}
|
||||||
$user->permissions = $permissions_array;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
$user->fill($request->all());
|
||||||
|
|
||||||
// Update the location of any assets checked out to this user
|
if ($user->id == $request->input('manager_id')) {
|
||||||
Asset::where('assigned_type', User::class)
|
return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot be your own manager'));
|
||||||
->where('assigned_to', $user->id)->update(['location_id' => $request->input('location_id', null)]);
|
}
|
||||||
|
|
||||||
|
if ($request->filled('password')) {
|
||||||
app('App\Http\Requests\ImageUploadRequest')->handleImages($user, 600, 'image', 'avatars', 'avatar');
|
$user->password = bcrypt($request->input('password'));
|
||||||
|
}
|
||||||
if ($user->save()) {
|
|
||||||
|
|
||||||
// Sync group memberships:
|
// We need to use has() instead of filled()
|
||||||
// This was changed in Snipe-IT v4.6.x to 4.7, since we upgraded to Laravel 5.5
|
// here because we need to overwrite permissions
|
||||||
// which changes the behavior of has vs filled.
|
// if someone needs to null them out
|
||||||
// The $request->has method will now return true even if the input value is an empty string or null.
|
if ($request->has('permissions')) {
|
||||||
// A new $request->filled method has was added that provides the previous behavior of the has method.
|
$permissions_array = $request->input('permissions');
|
||||||
|
|
||||||
// Check if the request has groups passed and has a value
|
// Strip out the individual superuser permission if the API user isn't a superadmin
|
||||||
if ($request->filled('groups')) {
|
if (!Auth::user()->isSuperUser()) {
|
||||||
$validator = Validator::make($request->all(), [
|
unset($permissions_array['superuser']);
|
||||||
'groups.*' => 'integer|exists:permission_groups,id',
|
|
||||||
]);
|
|
||||||
|
|
||||||
if ($validator->fails()){
|
|
||||||
return response()->json(Helper::formatStandardApiResponse('error', null, $user->getErrors()));
|
|
||||||
}
|
}
|
||||||
$user->groups()->sync($request->input('groups'));
|
|
||||||
// The groups field has been passed but it is null, so we should blank it out
|
$user->permissions = $permissions_array;
|
||||||
} elseif ($request->has('groups')) {
|
|
||||||
$user->groups()->sync([]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return response()->json(Helper::formatStandardApiResponse('success', (new UsersTransformer)->transformUser($user), trans('admin/users/message.success.update')));
|
// Update the location of any assets checked out to this user
|
||||||
|
Asset::where('assigned_type', User::class)
|
||||||
|
->where('assigned_to', $user->id)->update(['location_id' => $request->input('location_id', null)]);
|
||||||
|
|
||||||
|
|
||||||
|
app('App\Http\Requests\ImageUploadRequest')->handleImages($user, 600, 'image', 'avatars', 'avatar');
|
||||||
|
|
||||||
|
if ($user->save()) {
|
||||||
|
|
||||||
|
// Check if the request has groups passed and has a value, AND that the user us a superuser
|
||||||
|
if (($request->has('groups')) && (Auth::user()->isSuperUser())) {
|
||||||
|
|
||||||
|
$validator = Validator::make($request->only('groups'), [
|
||||||
|
'groups.*' => 'integer|exists:permission_groups,id',
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($validator->fails()) {
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('error', null, $validator->errors()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sync the groups since the user is a superuser and the groups pass validation
|
||||||
|
$user->groups()->sync($request->input('groups'));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('success', (new UsersTransformer)->transformUser($user), trans('admin/users/message.success.update')));
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('error', null, $user->getErrors()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return response()->json(Helper::formatStandardApiResponse('error', null, $user->getErrors()));
|
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found', compact('id'))));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -507,45 +518,36 @@ class UsersController extends Controller
|
|||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @since [v4.0]
|
* @since [v4.0]
|
||||||
* @param int $id
|
* @param int $id
|
||||||
* @return \Illuminate\Http\Response
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function destroy($id)
|
public function destroy(DeleteUserRequest $request, $id)
|
||||||
{
|
{
|
||||||
$this->authorize('delete', User::class);
|
$this->authorize('delete', User::class);
|
||||||
$user = User::findOrFail($id);
|
|
||||||
$this->authorize('delete', $user);
|
|
||||||
|
|
||||||
if (($user->assets) && ($user->assets->count() > 0)) {
|
if ($user = User::withTrashed()->find($id)) {
|
||||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.error.delete_has_assets')));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (($user->licenses) && ($user->licenses->count() > 0)) {
|
$this->authorize('delete', $user);
|
||||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'This user still has '.$user->licenses->count().' license(s) associated with them and cannot be deleted.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (($user->accessories) && ($user->accessories->count() > 0)) {
|
if ($user->delete()) {
|
||||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'This user still has '.$user->accessories->count().' accessories associated with them.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (($user->managedLocations()) && ($user->managedLocations()->count() > 0)) {
|
// Remove the user's avatar if they have one
|
||||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'This user still has '.$user->managedLocations()->count().' locations that they manage.'));
|
if (Storage::disk('public')->exists('avatars/' . $user->avatar)) {
|
||||||
}
|
try {
|
||||||
|
Storage::disk('public')->delete('avatars/' . $user->avatar);
|
||||||
if ($user->delete()) {
|
} catch (\Exception $e) {
|
||||||
|
Log::debug($e);
|
||||||
// Remove the user's avatar if they have one
|
}
|
||||||
if (Storage::disk('public')->exists('avatars/'.$user->avatar)) {
|
|
||||||
try {
|
|
||||||
Storage::disk('public')->delete('avatars/'.$user->avatar);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
\Log::debug($e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.success.delete')));
|
||||||
}
|
}
|
||||||
|
|
||||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.success.delete')));
|
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.error.delete')));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.error.delete')));
|
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found')));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -554,15 +556,42 @@ class UsersController extends Controller
|
|||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @since [v3.0]
|
* @since [v3.0]
|
||||||
* @param $userId
|
* @param $userId
|
||||||
* @return string JSON
|
* @return array | \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function assets(Request $request, $id)
|
public function assets(Request $request, $id)
|
||||||
{
|
{
|
||||||
$this->authorize('view', User::class);
|
$this->authorize('view', User::class);
|
||||||
$this->authorize('view', Asset::class);
|
$this->authorize('view', Asset::class);
|
||||||
$assets = Asset::where('assigned_to', '=', $id)->where('assigned_type', '=', User::class)->with('model')->get();
|
|
||||||
|
|
||||||
return (new AssetsTransformer)->transformAssets($assets, $assets->count(), $request);
|
if ($user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed()->find($id)) {
|
||||||
|
$this->authorize('view', $user);
|
||||||
|
|
||||||
|
$assets = Asset::where('assigned_to', '=', $id)->where('assigned_type', '=', User::class)->with('model');
|
||||||
|
|
||||||
|
|
||||||
|
// Filter on category ID
|
||||||
|
if ($request->filled('category_id')) {
|
||||||
|
$assets = $assets->InCategory($request->input('category_id'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Filter on model ID
|
||||||
|
if ($request->filled('model_id')) {
|
||||||
|
|
||||||
|
$model_ids = $request->input('model_id');
|
||||||
|
if (!is_array($model_ids)) {
|
||||||
|
$model_ids = array($model_ids);
|
||||||
|
}
|
||||||
|
$assets = $assets->InModelList($model_ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
$assets = $assets->get();
|
||||||
|
|
||||||
|
return (new AssetsTransformer)->transformAssets($assets, $assets->count(), $request);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found', compact('id'))));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -576,15 +605,22 @@ class UsersController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function emailAssetList(Request $request, $id)
|
public function emailAssetList(Request $request, $id)
|
||||||
{
|
{
|
||||||
$user = User::findOrFail($id);
|
$this->authorize('update', User::class);
|
||||||
|
|
||||||
if (empty($user->email)) {
|
if ($user = User::find($id)) {
|
||||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.inventorynotification.error')));
|
$this->authorize('update', $user);
|
||||||
|
|
||||||
|
if (empty($user->email)) {
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.inventorynotification.error')));
|
||||||
|
}
|
||||||
|
|
||||||
|
$user->notify((new CurrentInventory($user)));
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.inventorynotification.success')));
|
||||||
}
|
}
|
||||||
|
|
||||||
$user->notify((new CurrentInventory($user)));
|
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found', compact('id'))));
|
||||||
|
|
||||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.inventorynotification.success')));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -593,13 +629,14 @@ class UsersController extends Controller
|
|||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @since [v3.0]
|
* @since [v3.0]
|
||||||
* @param $userId
|
* @param $userId
|
||||||
* @return string JSON
|
* @return array | \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function consumables(Request $request, $id)
|
public function consumables(Request $request, $id)
|
||||||
{
|
{
|
||||||
$this->authorize('view', User::class);
|
$this->authorize('view', User::class);
|
||||||
$this->authorize('view', Consumable::class);
|
$this->authorize('view', Consumable::class);
|
||||||
$user = User::findOrFail($id);
|
$user = User::findOrFail($id);
|
||||||
|
$this->authorize('view', $user);
|
||||||
$consumables = $user->consumables;
|
$consumables = $user->consumables;
|
||||||
return (new ConsumablesTransformer)->transformConsumables($consumables, $consumables->count(), $request);
|
return (new ConsumablesTransformer)->transformConsumables($consumables, $consumables->count(), $request);
|
||||||
}
|
}
|
||||||
@@ -610,12 +647,13 @@ class UsersController extends Controller
|
|||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @since [v4.6.14]
|
* @since [v4.6.14]
|
||||||
* @param $userId
|
* @param $userId
|
||||||
* @return string JSON
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function accessories($id)
|
public function accessories($id)
|
||||||
{
|
{
|
||||||
$this->authorize('view', User::class);
|
$this->authorize('view', User::class);
|
||||||
$user = User::findOrFail($id);
|
$user = User::findOrFail($id);
|
||||||
|
$this->authorize('view', $user);
|
||||||
$this->authorize('view', Accessory::class);
|
$this->authorize('view', Accessory::class);
|
||||||
$accessories = $user->accessories;
|
$accessories = $user->accessories;
|
||||||
|
|
||||||
@@ -628,7 +666,7 @@ class UsersController extends Controller
|
|||||||
* @author [N. Mathar] [<snipe@snipe.net>]
|
* @author [N. Mathar] [<snipe@snipe.net>]
|
||||||
* @since [v5.0]
|
* @since [v5.0]
|
||||||
* @param $userId
|
* @param $userId
|
||||||
* @return string JSON
|
* @return array | \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function licenses($id)
|
public function licenses($id)
|
||||||
{
|
{
|
||||||
@@ -636,6 +674,7 @@ class UsersController extends Controller
|
|||||||
$this->authorize('view', License::class);
|
$this->authorize('view', License::class);
|
||||||
|
|
||||||
if ($user = User::where('id', $id)->withTrashed()->first()) {
|
if ($user = User::where('id', $id)->withTrashed()->first()) {
|
||||||
|
$this->authorize('update', $user);
|
||||||
$licenses = $user->licenses()->get();
|
$licenses = $user->licenses()->get();
|
||||||
return (new LicensesTransformer())->transformLicenses($licenses, $licenses->count());
|
return (new LicensesTransformer())->transformLicenses($licenses, $licenses->count());
|
||||||
}
|
}
|
||||||
@@ -659,9 +698,20 @@ class UsersController extends Controller
|
|||||||
if ($request->filled('id')) {
|
if ($request->filled('id')) {
|
||||||
try {
|
try {
|
||||||
$user = User::find($request->get('id'));
|
$user = User::find($request->get('id'));
|
||||||
|
$this->authorize('update', $user);
|
||||||
$user->two_factor_secret = null;
|
$user->two_factor_secret = null;
|
||||||
$user->two_factor_enrolled = 0;
|
$user->two_factor_enrolled = 0;
|
||||||
$user->save();
|
$user->saveQuietly();
|
||||||
|
|
||||||
|
// Log the reset
|
||||||
|
$logaction = new Actionlog();
|
||||||
|
$logaction->target_type = User::class;
|
||||||
|
$logaction->target_id = $user->id;
|
||||||
|
$logaction->item_type = User::class;
|
||||||
|
$logaction->item_id = $user->id;
|
||||||
|
$logaction->created_at = date('Y-m-d H:i:s');
|
||||||
|
$logaction->user_id = Auth::user()->id;
|
||||||
|
$logaction->logaction('2FA reset');
|
||||||
|
|
||||||
return response()->json(['message' => trans('admin/settings/general.two_factor_reset_success')], 200);
|
return response()->json(['message' => trans('admin/settings/general.two_factor_reset_success')], 200);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
@@ -679,7 +729,7 @@ class UsersController extends Controller
|
|||||||
* @author [Juan Font] [<juanfontalonso@gmail.com>]
|
* @author [Juan Font] [<juanfontalonso@gmail.com>]
|
||||||
* @since [v4.4.2]
|
* @since [v4.4.2]
|
||||||
* @param \Illuminate\Http\Request $request
|
* @param \Illuminate\Http\Request $request
|
||||||
* @return \Illuminate\Http\Response
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getCurrentUserInfo(Request $request)
|
public function getCurrentUserInfo(Request $request)
|
||||||
{
|
{
|
||||||
@@ -692,12 +742,14 @@ class UsersController extends Controller
|
|||||||
* @author [E. Taylor] [<dev@evantaylor.name>]
|
* @author [E. Taylor] [<dev@evantaylor.name>]
|
||||||
* @param int $userId
|
* @param int $userId
|
||||||
* @since [v6.0.0]
|
* @since [v6.0.0]
|
||||||
* @return JsonResponse
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function restore($userId = null)
|
public function restore($userId)
|
||||||
{
|
{
|
||||||
|
$this->authorize('delete', User::class);
|
||||||
|
|
||||||
if ($user = User::withTrashed()->find($userId)) {
|
if ($user = User::withTrashed()->find($userId)) {
|
||||||
|
|
||||||
$this->authorize('delete', $user);
|
$this->authorize('delete', $user);
|
||||||
|
|
||||||
if ($user->deleted_at == '') {
|
if ($user->deleted_at == '') {
|
||||||
@@ -716,8 +768,6 @@ class UsersController extends Controller
|
|||||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.success.restored')), 200);
|
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.success.restored')), 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check validation to make sure we're not restoring a user with the same username as an existing user
|
|
||||||
return response()->json(Helper::formatStandardApiResponse('error', null, $user->getErrors()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found')), 200);
|
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found')), 200);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use App\Helpers\Helper;
|
|||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use App\Models\AssetMaintenance;
|
use App\Models\AssetMaintenance;
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
use Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Slack;
|
use Slack;
|
||||||
|
|||||||
@@ -7,16 +7,16 @@ use App\Http\Requests\ImageUploadRequest;
|
|||||||
use App\Models\Actionlog;
|
use App\Models\Actionlog;
|
||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use App\Models\AssetModel;
|
use App\Models\AssetModel;
|
||||||
|
use App\Models\CustomField;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Input;
|
|
||||||
use Illuminate\Support\Facades\View;
|
use Illuminate\Support\Facades\View;
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Redirect;
|
use Illuminate\Http\Request;
|
||||||
use Request;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Storage;
|
|
||||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class controls all actions related to asset models for
|
* This class controls all actions related to asset models for
|
||||||
@@ -66,7 +66,7 @@ class AssetModelsController extends Controller
|
|||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @since [v1.0]
|
* @since [v1.0]
|
||||||
* @param ImageUploadRequest $request
|
* @param ImageUploadRequest $request
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
*/
|
*/
|
||||||
public function store(ImageUploadRequest $request)
|
public function store(ImageUploadRequest $request)
|
||||||
@@ -85,7 +85,7 @@ class AssetModelsController extends Controller
|
|||||||
$model->category_id = $request->input('category_id');
|
$model->category_id = $request->input('category_id');
|
||||||
$model->notes = $request->input('notes');
|
$model->notes = $request->input('notes');
|
||||||
$model->user_id = Auth::id();
|
$model->user_id = Auth::id();
|
||||||
$model->requestable = Request::has('requestable');
|
$model->requestable = $request->has('requestable');
|
||||||
|
|
||||||
if ($request->input('fieldset_id') != '') {
|
if ($request->input('fieldset_id') != '') {
|
||||||
$model->fieldset_id = $request->input('fieldset_id');
|
$model->fieldset_id = $request->input('fieldset_id');
|
||||||
@@ -139,7 +139,7 @@ class AssetModelsController extends Controller
|
|||||||
* @since [v1.0]
|
* @since [v1.0]
|
||||||
* @param ImageUploadRequest $request
|
* @param ImageUploadRequest $request
|
||||||
* @param int $modelId
|
* @param int $modelId
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
*/
|
*/
|
||||||
public function update(ImageUploadRequest $request, $modelId = null)
|
public function update(ImageUploadRequest $request, $modelId = null)
|
||||||
@@ -200,7 +200,7 @@ class AssetModelsController extends Controller
|
|||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @since [v1.0]
|
* @since [v1.0]
|
||||||
* @param int $modelId
|
* @param int $modelId
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
*/
|
*/
|
||||||
public function destroy($modelId)
|
public function destroy($modelId)
|
||||||
@@ -220,7 +220,7 @@ class AssetModelsController extends Controller
|
|||||||
try {
|
try {
|
||||||
Storage::disk('public')->delete('models/'.$model->image);
|
Storage::disk('public')->delete('models/'.$model->image);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
\Log::info($e);
|
Log::info($e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,7 +237,7 @@ class AssetModelsController extends Controller
|
|||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @since [v1.0]
|
* @since [v1.0]
|
||||||
* @param int $id
|
* @param int $id
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
*/
|
*/
|
||||||
public function getRestore($id)
|
public function getRestore($id)
|
||||||
@@ -288,7 +288,7 @@ class AssetModelsController extends Controller
|
|||||||
public function show($modelId = null)
|
public function show($modelId = null)
|
||||||
{
|
{
|
||||||
$this->authorize('view', AssetModel::class);
|
$this->authorize('view', AssetModel::class);
|
||||||
$model = AssetModel::withTrashed()->withCount('assets')->find($modelId);
|
$model = AssetModel::withTrashed()->find($modelId);
|
||||||
|
|
||||||
if (isset($model->id)) {
|
if (isset($model->id)) {
|
||||||
return view('models/view', compact('model'));
|
return view('models/view', compact('model'));
|
||||||
@@ -429,7 +429,7 @@ class AssetModelsController extends Controller
|
|||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @since [v1.0]
|
* @since [v1.0]
|
||||||
* @param int $modelId
|
* @param int $modelId
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function postBulkDelete(Request $request)
|
public function postBulkDelete(Request $request)
|
||||||
{
|
{
|
||||||
@@ -486,11 +486,11 @@ class AssetModelsController extends Controller
|
|||||||
* @param array $defaultValues
|
* @param array $defaultValues
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
private function assignCustomFieldsDefaultValues(AssetModel $model, array $defaultValues)
|
private function assignCustomFieldsDefaultValues(AssetModel $model, array $defaultValues): bool
|
||||||
{
|
{
|
||||||
$data = array();
|
$data = array();
|
||||||
foreach ($defaultValues as $customFieldId => $defaultValue) {
|
foreach ($defaultValues as $customFieldId => $defaultValue) {
|
||||||
$customField = \App\Models\CustomField::find($customFieldId);
|
$customField = CustomField::find($customFieldId);
|
||||||
|
|
||||||
$data[$customField->db_column] = $defaultValue;
|
$data[$customField->db_column] = $defaultValue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ class AssetModelsFilesController extends Controller
|
|||||||
*
|
*
|
||||||
* @param UploadFileRequest $request
|
* @param UploadFileRequest $request
|
||||||
* @param int $modelId
|
* @param int $modelId
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
*@since [v1.0]
|
*@since [v1.0]
|
||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
@@ -38,7 +38,7 @@ class AssetModelsFilesController extends Controller
|
|||||||
|
|
||||||
$file_name = $request->handleFile('private_uploads/assetmodels/','model-'.$model->id,$file);
|
$file_name = $request->handleFile('private_uploads/assetmodels/','model-'.$model->id,$file);
|
||||||
|
|
||||||
$model->logUpload($file_name, e($request->get('notes')));
|
$model->logUpload($file_name, $request->get('notes'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return redirect()->back()->with('success', trans('general.file_upload_success'));
|
return redirect()->back()->with('success', trans('general.file_upload_success'));
|
||||||
@@ -70,8 +70,6 @@ class AssetModelsFilesController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
$file = 'private_uploads/assetmodels/'.$log->filename;
|
$file = 'private_uploads/assetmodels/'.$log->filename;
|
||||||
\Log::debug('Checking for '.$file);
|
|
||||||
|
|
||||||
|
|
||||||
if (! Storage::exists($file)) {
|
if (! Storage::exists($file)) {
|
||||||
return response('File '.$file.' not found on server', 404)
|
return response('File '.$file.' not found on server', 404)
|
||||||
|
|||||||
@@ -12,8 +12,9 @@ use App\Models\CheckoutAcceptance;
|
|||||||
use App\Models\LicenseSeat;
|
use App\Models\LicenseSeat;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Redirect;
|
use Illuminate\Support\Facades\Session;
|
||||||
use Illuminate\Support\Facades\View;
|
use Illuminate\Support\Facades\View;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class AssetCheckinController extends Controller
|
class AssetCheckinController extends Controller
|
||||||
{
|
{
|
||||||
@@ -39,7 +40,17 @@ class AssetCheckinController extends Controller
|
|||||||
|
|
||||||
$this->authorize('checkin', $asset);
|
$this->authorize('checkin', $asset);
|
||||||
|
|
||||||
return view('hardware/checkin', compact('asset'))->with('statusLabel_list', Helper::statusLabelList())->with('backto', $backto);
|
// This asset is already checked in, redirect
|
||||||
|
|
||||||
|
if (is_null($asset->assignedTo)) {
|
||||||
|
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkin.already_checked_in'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$asset->model) {
|
||||||
|
return redirect()->route('hardware.show', $asset->id)->with('error', trans('admin/hardware/general.model_invalid_fix'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('hardware/checkin', compact('asset'))->with('statusLabel_list', Helper::statusLabelList())->with('backto', $backto)->with('table_name', 'Assets');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -49,7 +60,7 @@ class AssetCheckinController extends Controller
|
|||||||
* @param AssetCheckinRequest $request
|
* @param AssetCheckinRequest $request
|
||||||
* @param int $assetId
|
* @param int $assetId
|
||||||
* @param null $backto
|
* @param null $backto
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
* @since [v1.0]
|
* @since [v1.0]
|
||||||
*/
|
*/
|
||||||
@@ -64,6 +75,11 @@ class AssetCheckinController extends Controller
|
|||||||
if (is_null($target = $asset->assignedTo)) {
|
if (is_null($target = $asset->assignedTo)) {
|
||||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkin.already_checked_in'));
|
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkin.already_checked_in'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$asset->model) {
|
||||||
|
return redirect()->route('hardware.show', $asset->id)->with('error', trans('admin/hardware/general.model_invalid_fix'));
|
||||||
|
}
|
||||||
|
|
||||||
$this->authorize('checkin', $asset);
|
$this->authorize('checkin', $asset);
|
||||||
|
|
||||||
if ($asset->assignedType() == Asset::USER) {
|
if ($asset->assignedType() == Asset::USER) {
|
||||||
@@ -86,7 +102,7 @@ class AssetCheckinController extends Controller
|
|||||||
$asset->location_id = $asset->rtd_location_id;
|
$asset->location_id = $asset->rtd_location_id;
|
||||||
|
|
||||||
if ($request->filled('location_id')) {
|
if ($request->filled('location_id')) {
|
||||||
\Log::debug('NEW Location ID: '.$request->get('location_id'));
|
Log::debug('NEW Location ID: '.$request->get('location_id'));
|
||||||
$asset->location_id = $request->get('location_id');
|
$asset->location_id = $request->get('location_id');
|
||||||
|
|
||||||
if ($request->get('update_default_location') == 0){
|
if ($request->get('update_default_location') == 0){
|
||||||
@@ -116,15 +132,12 @@ class AssetCheckinController extends Controller
|
|||||||
$acceptance->delete();
|
$acceptance->delete();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Session::put('redirect_option', $request->get('redirect_option'));
|
||||||
// Was the asset updated?
|
// Was the asset updated?
|
||||||
if ($asset->save()) {
|
if ($asset->save()) {
|
||||||
|
|
||||||
event(new CheckoutableCheckedIn($asset, $target, Auth::user(), $request->input('note'), $checkin_at, $originalValues));
|
event(new CheckoutableCheckedIn($asset, $target, Auth::user(), $request->input('note'), $checkin_at, $originalValues));
|
||||||
|
return Helper::getRedirectOption($asset, $assetId, 'Assets');
|
||||||
if ((isset($user)) && ($backto == 'user')) {
|
|
||||||
return redirect()->route('users.show', $user->id)->with('success', trans('admin/hardware/message.checkin.success'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return redirect()->route('hardware.index')->with('success', trans('admin/hardware/message.checkin.success'));
|
|
||||||
}
|
}
|
||||||
// Redirect to the asset management page with error
|
// Redirect to the asset management page with error
|
||||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkin.error').$asset->getErrors());
|
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkin.error').$asset->getErrors());
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use App\Http\Requests\AssetCheckoutRequest;
|
|||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Session;
|
||||||
|
|
||||||
class AssetCheckoutController extends Controller
|
class AssetCheckoutController extends Controller
|
||||||
{
|
{
|
||||||
@@ -33,11 +34,17 @@ class AssetCheckoutController extends Controller
|
|||||||
|
|
||||||
$this->authorize('checkout', $asset);
|
$this->authorize('checkout', $asset);
|
||||||
|
|
||||||
|
if (!$asset->model) {
|
||||||
|
return redirect()->route('hardware.show', $asset->id)->with('error', trans('admin/hardware/general.model_invalid_fix'));
|
||||||
|
}
|
||||||
|
|
||||||
if ($asset->availableForCheckout()) {
|
if ($asset->availableForCheckout()) {
|
||||||
return view('hardware/checkout', compact('asset'))
|
return view('hardware/checkout', compact('asset'))
|
||||||
->with('statusLabel_list', Helper::deployableStatusLabelList());
|
->with('statusLabel_list', Helper::deployableStatusLabelList())
|
||||||
|
->with('table_name', 'Assets');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkout.not_available'));
|
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkout.not_available'));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +54,7 @@ class AssetCheckoutController extends Controller
|
|||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @param AssetCheckoutRequest $request
|
* @param AssetCheckoutRequest $request
|
||||||
* @param int $assetId
|
* @param int $assetId
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
* @since [v1.0]
|
* @since [v1.0]
|
||||||
*/
|
*/
|
||||||
public function store(AssetCheckoutRequest $request, $assetId)
|
public function store(AssetCheckoutRequest $request, $assetId)
|
||||||
@@ -60,9 +67,14 @@ class AssetCheckoutController extends Controller
|
|||||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkout.not_available'));
|
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkout.not_available'));
|
||||||
}
|
}
|
||||||
$this->authorize('checkout', $asset);
|
$this->authorize('checkout', $asset);
|
||||||
|
|
||||||
|
if (!$asset->model) {
|
||||||
|
return redirect()->route('hardware.show', $asset->id)->with('error', trans('admin/hardware/general.model_invalid_fix'));
|
||||||
|
}
|
||||||
|
|
||||||
$admin = Auth::user();
|
$admin = Auth::user();
|
||||||
|
|
||||||
$target = $this->determineCheckoutTarget($asset);
|
$target = $this->determineCheckoutTarget();
|
||||||
|
|
||||||
$asset = $this->updateAssetLocation($asset, $target);
|
$asset = $this->updateAssetLocation($asset, $target);
|
||||||
|
|
||||||
@@ -97,11 +109,12 @@ class AssetCheckoutController extends Controller
|
|||||||
return redirect()->to("hardware/$assetId/checkout")->with('error', trans('general.error_user_company'));
|
return redirect()->to("hardware/$assetId/checkout")->with('error', trans('general.error_user_company'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($asset->checkOut($target, $admin, $checkout_at, $expected_checkin, $request->get('note'), $request->get('name'))) {
|
|
||||||
return redirect()->route('hardware.index')->with('success', trans('admin/hardware/message.checkout.success'));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Session::put(['redirect_option' => $request->get('redirect_option'), 'checkout_to_type' => $request->get('checkout_to_type')]);
|
||||||
|
|
||||||
|
if ($asset->checkOut($target, $admin, $checkout_at, $expected_checkin, $request->get('note'), $request->get('name'))) {
|
||||||
|
return Helper::getRedirectOption($request, $assetId, 'Assets');
|
||||||
|
}
|
||||||
// Redirect to the asset management page with error
|
// Redirect to the asset management page with error
|
||||||
return redirect()->to("hardware/$assetId/checkout")->with('error', trans('admin/hardware/message.checkout.error').$asset->getErrors());
|
return redirect()->to("hardware/$assetId/checkout")->with('error', trans('admin/hardware/message.checkout.error').$asset->getErrors());
|
||||||
} catch (ModelNotFoundException $e) {
|
} catch (ModelNotFoundException $e) {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ class AssetFilesController extends Controller
|
|||||||
*
|
*
|
||||||
* @param UploadFileRequest $request
|
* @param UploadFileRequest $request
|
||||||
* @param int $assetId
|
* @param int $assetId
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
*@since [v1.0]
|
*@since [v1.0]
|
||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
@@ -38,7 +38,7 @@ class AssetFilesController extends Controller
|
|||||||
foreach ($request->file('file') as $file) {
|
foreach ($request->file('file') as $file) {
|
||||||
$file_name = $request->handleFile('private_uploads/assets/','hardware-'.$asset->id, $file);
|
$file_name = $request->handleFile('private_uploads/assets/','hardware-'.$asset->id, $file);
|
||||||
|
|
||||||
$asset->logUpload($file_name, e($request->get('notes')));
|
$asset->logUpload($file_name, $request->get('notes'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return redirect()->back()->with('success', trans('admin/hardware/message.upload.success'));
|
return redirect()->back()->with('success', trans('admin/hardware/message.upload.success'));
|
||||||
@@ -70,7 +70,6 @@ class AssetFilesController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
$file = 'private_uploads/assets/'.$log->filename;
|
$file = 'private_uploads/assets/'.$log->filename;
|
||||||
\Log::debug('Checking for '.$file);
|
|
||||||
|
|
||||||
if ($log->action_type == 'audit') {
|
if ($log->action_type == 'audit') {
|
||||||
$file = 'private_uploads/audits/'.$log->filename;
|
$file = 'private_uploads/audits/'.$log->filename;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use App\Helpers\Helper;
|
|||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Http\Requests\ImageUploadRequest;
|
use App\Http\Requests\ImageUploadRequest;
|
||||||
use App\Models\Actionlog;
|
use App\Models\Actionlog;
|
||||||
use App\Models\Manufacturer;
|
use App\Http\Requests\UploadFileRequest;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use App\Models\AssetModel;
|
use App\Models\AssetModel;
|
||||||
@@ -96,12 +96,16 @@ class AssetsController extends Controller
|
|||||||
*
|
*
|
||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @since [v1.0]
|
* @since [v1.0]
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function store(ImageUploadRequest $request)
|
public function store(ImageUploadRequest $request)
|
||||||
{
|
{
|
||||||
$this->authorize(Asset::class);
|
$this->authorize(Asset::class);
|
||||||
|
|
||||||
|
// There are a lot more rules to add here but prevents
|
||||||
|
// errors around `asset_tags` not being present below.
|
||||||
|
$this->validate($request, ['asset_tags' => ['required', 'array']]);
|
||||||
|
|
||||||
// Handle asset tags - there could be one, or potentially many.
|
// Handle asset tags - there could be one, or potentially many.
|
||||||
// This is only necessary on create, not update, since bulk editing is handled
|
// This is only necessary on create, not update, since bulk editing is handled
|
||||||
// differently
|
// differently
|
||||||
@@ -156,29 +160,7 @@ class AssetsController extends Controller
|
|||||||
$asset = $request->handleImages($asset);
|
$asset = $request->handleImages($asset);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update custom fields in the database.
|
$asset = $asset->handleCustomFieldsForStoring($request);
|
||||||
// Validation for these fields is handled through the AssetRequest form request
|
|
||||||
$model = AssetModel::find($request->get('model_id'));
|
|
||||||
|
|
||||||
if (($model) && ($model->fieldset)) {
|
|
||||||
foreach ($model->fieldset->fields as $field) {
|
|
||||||
if ($field->field_encrypted == '1') {
|
|
||||||
if (Gate::allows('admin')) {
|
|
||||||
if (is_array($request->input($field->db_column))) {
|
|
||||||
$asset->{$field->db_column} = Crypt::encrypt(implode(', ', $request->input($field->db_column)));
|
|
||||||
} else {
|
|
||||||
$asset->{$field->db_column} = Crypt::encrypt($request->input($field->db_column));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (is_array($request->input($field->db_column))) {
|
|
||||||
$asset->{$field->db_column} = implode(', ', $request->input($field->db_column));
|
|
||||||
} else {
|
|
||||||
$asset->{$field->db_column} = $request->input($field->db_column);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate the asset before saving
|
// Validate the asset before saving
|
||||||
if ($asset->isValid() && $asset->save()) {
|
if ($asset->isValid() && $asset->save()) {
|
||||||
@@ -203,7 +185,7 @@ class AssetsController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($success) {
|
if ($success) {
|
||||||
\Log::debug(e($asset->asset_tag));
|
Log::debug(e($asset->asset_tag));
|
||||||
return redirect()->route('hardware.index')
|
return redirect()->route('hardware.index')
|
||||||
->with('success-unescaped', trans('admin/hardware/message.create.success_linked', ['link' => route('hardware.show', $asset->id), 'id', 'tag' => e($asset->asset_tag)]));
|
->with('success-unescaped', trans('admin/hardware/message.create.success_linked', ['link' => route('hardware.show', $asset->id), 'id', 'tag' => e($asset->asset_tag)]));
|
||||||
|
|
||||||
@@ -289,7 +271,7 @@ class AssetsController extends Controller
|
|||||||
*
|
*
|
||||||
* @param int $assetId
|
* @param int $assetId
|
||||||
* @return \Illuminate\Http\RedirectResponse|Redirect
|
* @return \Illuminate\Http\RedirectResponse|Redirect
|
||||||
*@since [v1.0]
|
* @since [v1.0]
|
||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
*/
|
*/
|
||||||
public function update(ImageUploadRequest $request, $assetId = null)
|
public function update(ImageUploadRequest $request, $assetId = null)
|
||||||
@@ -304,7 +286,8 @@ class AssetsController extends Controller
|
|||||||
$asset->status_id = $request->input('status_id', null);
|
$asset->status_id = $request->input('status_id', null);
|
||||||
$asset->warranty_months = $request->input('warranty_months', null);
|
$asset->warranty_months = $request->input('warranty_months', null);
|
||||||
$asset->purchase_cost = $request->input('purchase_cost', null);
|
$asset->purchase_cost = $request->input('purchase_cost', null);
|
||||||
$asset->purchase_date = $request->input('purchase_date', null);
|
$asset->purchase_date = $request->input('purchase_date', null);
|
||||||
|
$asset->next_audit_date = $request->input('next_audit_date', null);
|
||||||
if ($request->filled('purchase_date') && !$request->filled('asset_eol_date') && ($asset->model->eol > 0)) {
|
if ($request->filled('purchase_date') && !$request->filled('asset_eol_date') && ($asset->model->eol > 0)) {
|
||||||
$asset->purchase_date = $request->input('purchase_date', null);
|
$asset->purchase_date = $request->input('purchase_date', null);
|
||||||
$asset->asset_eol_date = Carbon::parse($request->input('purchase_date'))->addMonths($asset->model->eol)->format('Y-m-d');
|
$asset->asset_eol_date = Carbon::parse($request->input('purchase_date'))->addMonths($asset->model->eol)->format('Y-m-d');
|
||||||
@@ -365,32 +348,7 @@ class AssetsController extends Controller
|
|||||||
$asset->notes = $request->input('notes');
|
$asset->notes = $request->input('notes');
|
||||||
|
|
||||||
$asset = $request->handleImages($asset);
|
$asset = $request->handleImages($asset);
|
||||||
|
$asset = $asset->handleCustomFieldsForStoring($request);
|
||||||
// Update custom fields in the database.
|
|
||||||
// Validation for these fields is handlded through the AssetRequest form request
|
|
||||||
// FIXME: No idea why this is returning a Builder error on db_column_name.
|
|
||||||
// Need to investigate and fix. Using static method for now.
|
|
||||||
$model = AssetModel::find($request->get('model_id'));
|
|
||||||
if (($model) && ($model->fieldset)) {
|
|
||||||
foreach ($model->fieldset->fields as $field) {
|
|
||||||
if ($field->field_encrypted == '1') {
|
|
||||||
if (Gate::allows('admin')) {
|
|
||||||
if (is_array($request->input($field->db_column))) {
|
|
||||||
$asset->{$field->db_column} = Crypt::encrypt(implode(', ', $request->input($field->db_column)));
|
|
||||||
} else {
|
|
||||||
$asset->{$field->db_column} = Crypt::encrypt($request->input($field->db_column));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (is_array($request->input($field->db_column))) {
|
|
||||||
$asset->{$field->db_column} = implode(', ', $request->input($field->db_column));
|
|
||||||
} else {
|
|
||||||
$asset->{$field->db_column} = $request->input($field->db_column);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if ($asset->save()) {
|
if ($asset->save()) {
|
||||||
return redirect()->route('hardware.show', $assetId)
|
return redirect()->route('hardware.show', $assetId)
|
||||||
@@ -406,7 +364,7 @@ class AssetsController extends Controller
|
|||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @param int $assetId
|
* @param int $assetId
|
||||||
* @since [v1.0]
|
* @since [v1.0]
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function destroy($assetId)
|
public function destroy($assetId)
|
||||||
{
|
{
|
||||||
@@ -440,7 +398,7 @@ class AssetsController extends Controller
|
|||||||
*
|
*
|
||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @since [v3.0]
|
* @since [v3.0]
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function getAssetBySerial(Request $request)
|
public function getAssetBySerial(Request $request)
|
||||||
{
|
{
|
||||||
@@ -458,7 +416,7 @@ class AssetsController extends Controller
|
|||||||
*
|
*
|
||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @since [v3.0]
|
* @since [v3.0]
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function getAssetByTag(Request $request, $tag=null)
|
public function getAssetByTag(Request $request, $tag=null)
|
||||||
{
|
{
|
||||||
@@ -850,15 +808,15 @@ class AssetsController extends Controller
|
|||||||
return view('hardware/audit-due');
|
return view('hardware/audit-due');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function overdueForAudit()
|
public function dueForCheckin()
|
||||||
{
|
{
|
||||||
$this->authorize('audit', Asset::class);
|
$this->authorize('checkin', Asset::class);
|
||||||
|
|
||||||
return view('hardware/audit-overdue');
|
return view('hardware/checkin-due');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function auditStore(Request $request, $id)
|
public function auditStore(UploadFileRequest $request, $id)
|
||||||
{
|
{
|
||||||
$this->authorize('audit', Asset::class);
|
$this->authorize('audit', Asset::class);
|
||||||
|
|
||||||
@@ -875,7 +833,21 @@ class AssetsController extends Controller
|
|||||||
|
|
||||||
$asset = Asset::findOrFail($id);
|
$asset = Asset::findOrFail($id);
|
||||||
|
|
||||||
// We don't want to log this as a normal update, so let's bypass that
|
/**
|
||||||
|
* Even though we do a save() further down, we don't want to log this as a "normal" asset update,
|
||||||
|
* which would trigger the Asset Observer and would log an asset *update* log entry (because the
|
||||||
|
* de-normed fields like next_audit_date on the asset itself will change on save()) *in addition* to
|
||||||
|
* the audit log entry we're creating through this controller.
|
||||||
|
*
|
||||||
|
* To prevent this double-logging (one for update and one for audit), we skip the observer and bypass
|
||||||
|
* that de-normed update log entry by using unsetEventDispatcher(), BUT invoking unsetEventDispatcher()
|
||||||
|
* will bypass normal model-level validation that's usually handled at the observer )
|
||||||
|
*
|
||||||
|
* We handle validation on the save() by checking if the asset is valid via the ->isValid() method,
|
||||||
|
* which manually invokes Watson Validating to make sure the asset's model is valid.
|
||||||
|
*
|
||||||
|
* @see \App\Observers\AssetObserver::updating()
|
||||||
|
*/
|
||||||
$asset->unsetEventDispatcher();
|
$asset->unsetEventDispatcher();
|
||||||
|
|
||||||
$asset->next_audit_date = $request->input('next_audit_date');
|
$asset->next_audit_date = $request->input('next_audit_date');
|
||||||
@@ -884,29 +856,27 @@ class AssetsController extends Controller
|
|||||||
// Check to see if they checked the box to update the physical location,
|
// Check to see if they checked the box to update the physical location,
|
||||||
// not just note it in the audit notes
|
// not just note it in the audit notes
|
||||||
if ($request->input('update_location') == '1') {
|
if ($request->input('update_location') == '1') {
|
||||||
Log::debug('update location in audit');
|
|
||||||
$asset->location_id = $request->input('location_id');
|
$asset->location_id = $request->input('location_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoke Watson Validating to check the asset itself and check to make sure it saved correctly.
|
||||||
|
* We have to invoke this manually because of the unsetEventDispatcher() above.)
|
||||||
|
*/
|
||||||
|
if ($asset->isValid() && $asset->save()) {
|
||||||
|
|
||||||
if ($asset->save()) {
|
$file_name = null;
|
||||||
$file_name = '';
|
// Create the image (if one was chosen.)
|
||||||
// Upload an image, if attached
|
|
||||||
if ($request->hasFile('image')) {
|
if ($request->hasFile('image')) {
|
||||||
$path = 'private_uploads/audits';
|
$file_name = $request->handleFile('private_uploads/audits/', 'audit-'.$asset->id, $request->file('image'));
|
||||||
if (! Storage::exists($path)) {
|
|
||||||
Storage::makeDirectory($path, 775);
|
|
||||||
}
|
|
||||||
$upload = $image = $request->file('image');
|
|
||||||
$ext = $image->getClientOriginalExtension();
|
|
||||||
$file_name = 'audit-'.str_random(18).'.'.$ext;
|
|
||||||
Storage::putFileAs($path, $upload, $file_name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$asset->logAudit($request->input('note'), $request->input('location_id'), $file_name);
|
$asset->logAudit($request->input('note'), $request->input('location_id'), $file_name);
|
||||||
return redirect()->route('assets.audit.due')->with('success', trans('admin/hardware/message.audit.success'));
|
return redirect()->route('assets.audit.due')->with('success', trans('admin/hardware/message.audit.success'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return redirect()->back()->withInput()->withErrors($asset->getErrors());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getRequestedIndex($user_id = null)
|
public function getRequestedIndex($user_id = null)
|
||||||
|
|||||||
@@ -13,7 +13,10 @@ use App\Models\Setting;
|
|||||||
use App\View\Label;
|
use App\View\Label;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Crypt;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Gate;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
use Illuminate\Support\Facades\Session;
|
use Illuminate\Support\Facades\Session;
|
||||||
use App\Http\Requests\AssetCheckoutRequest;
|
use App\Http\Requests\AssetCheckoutRequest;
|
||||||
use App\Models\CustomField;
|
use App\Models\CustomField;
|
||||||
@@ -93,6 +96,59 @@ class BulkAssetsController extends Controller
|
|||||||
|
|
||||||
$assets = Asset::with('assignedTo', 'location', 'model')->whereIn('assets.id', $asset_ids);
|
$assets = Asset::with('assignedTo', 'location', 'model')->whereIn('assets.id', $asset_ids);
|
||||||
|
|
||||||
|
$assets = $assets->get();
|
||||||
|
|
||||||
|
if ($assets->isEmpty()) {
|
||||||
|
Log::debug('No assets were found for the provided IDs', ['ids' => $asset_ids]);
|
||||||
|
return redirect()->back()->with('error', trans('admin/hardware/message.update.assets_do_not_exist_or_are_invalid'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$models = $assets->unique('model_id');
|
||||||
|
$modelNames = [];
|
||||||
|
foreach($models as $model) {
|
||||||
|
$modelNames[] = $model->model->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->filled('bulk_actions')) {
|
||||||
|
|
||||||
|
|
||||||
|
switch ($request->input('bulk_actions')) {
|
||||||
|
case 'labels':
|
||||||
|
$this->authorize('view', Asset::class);
|
||||||
|
|
||||||
|
return (new Label)
|
||||||
|
->with('assets', $assets)
|
||||||
|
->with('settings', Setting::getSettings())
|
||||||
|
->with('bulkedit', true)
|
||||||
|
->with('count', 0);
|
||||||
|
|
||||||
|
case 'delete':
|
||||||
|
$this->authorize('delete', Asset::class);
|
||||||
|
$assets->each(function ($assets) {
|
||||||
|
$this->authorize('delete', $assets);
|
||||||
|
});
|
||||||
|
|
||||||
|
return view('hardware/bulk-delete')->with('assets', $assets);
|
||||||
|
|
||||||
|
case 'restore':
|
||||||
|
$this->authorize('update', Asset::class);
|
||||||
|
$assets = Asset::withTrashed()->find($asset_ids);
|
||||||
|
$assets->each(function ($asset) {
|
||||||
|
$this->authorize('delete', $asset);
|
||||||
|
});
|
||||||
|
return view('hardware/bulk-restore')->with('assets', $assets);
|
||||||
|
|
||||||
|
case 'edit':
|
||||||
|
$this->authorize('update', Asset::class);
|
||||||
|
|
||||||
|
return view('hardware/bulk')
|
||||||
|
->with('assets', $asset_ids)
|
||||||
|
->with('statuslabel_list', Helper::statusLabelList())
|
||||||
|
->with('models', $models->pluck(['model']))
|
||||||
|
->with('modelNames', $modelNames);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch ($sort_override) {
|
switch ($sort_override) {
|
||||||
case 'model':
|
case 'model':
|
||||||
$assets->OrderModels($order);
|
$assets->OrderModels($order);
|
||||||
@@ -128,54 +184,6 @@ class BulkAssetsController extends Controller
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
$assets = $assets->get();
|
|
||||||
|
|
||||||
$models = $assets->unique('model_id');
|
|
||||||
$modelNames = [];
|
|
||||||
foreach($models as $model) {
|
|
||||||
$modelNames[] = $model->model->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($request->filled('bulk_actions')) {
|
|
||||||
|
|
||||||
|
|
||||||
switch ($request->input('bulk_actions')) {
|
|
||||||
case 'labels':
|
|
||||||
$this->authorize('view', Asset::class);
|
|
||||||
|
|
||||||
return (new Label)
|
|
||||||
->with('assets', $assets)
|
|
||||||
->with('settings', Setting::getSettings())
|
|
||||||
->with('bulkedit', true)
|
|
||||||
->with('count', 0);
|
|
||||||
|
|
||||||
case 'delete':
|
|
||||||
$this->authorize('delete', Asset::class);
|
|
||||||
$assets->each(function ($assets) {
|
|
||||||
$this->authorize('delete', $assets);
|
|
||||||
});
|
|
||||||
|
|
||||||
return view('hardware/bulk-delete')->with('assets', $assets);
|
|
||||||
|
|
||||||
case 'restore':
|
|
||||||
$this->authorize('update', Asset::class);
|
|
||||||
$assets = Asset::withTrashed()->find($asset_ids);
|
|
||||||
$assets->each(function ($asset) {
|
|
||||||
$this->authorize('delete', $asset);
|
|
||||||
});
|
|
||||||
return view('hardware/bulk-restore')->with('assets', $assets);
|
|
||||||
|
|
||||||
case 'edit':
|
|
||||||
$this->authorize('update', Asset::class);
|
|
||||||
|
|
||||||
return view('hardware/bulk')
|
|
||||||
->with('assets', $asset_ids)
|
|
||||||
->with('statuslabel_list', Helper::statusLabelList())
|
|
||||||
->with('models', $models->pluck(['model']))
|
|
||||||
->with('modelNames', $modelNames);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return redirect()->back()->with('error', 'No action selected');
|
return redirect()->back()->with('error', 'No action selected');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,7 +191,6 @@ class BulkAssetsController extends Controller
|
|||||||
* Save bulk edits
|
* Save bulk edits
|
||||||
*
|
*
|
||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @return Redirect
|
|
||||||
* @internal param array $assets
|
* @internal param array $assets
|
||||||
* @since [v2.0]
|
* @since [v2.0]
|
||||||
*/
|
*/
|
||||||
@@ -208,7 +215,7 @@ class BulkAssetsController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$assets = Asset::whereIn('id', array_keys($request->input('ids')))->get();
|
$assets = Asset::whereIn('id', $request->input('ids'))->get();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -373,28 +380,30 @@ class BulkAssetsController extends Controller
|
|||||||
foreach ($asset->model->fieldset->fields as $field) {
|
foreach ($asset->model->fieldset->fields as $field) {
|
||||||
|
|
||||||
if ((array_key_exists($field->db_column, $this->update_array)) && ($field->field_encrypted == '1')) {
|
if ((array_key_exists($field->db_column, $this->update_array)) && ($field->field_encrypted == '1')) {
|
||||||
$decrypted_old = Helper::gracefulDecrypt($field, $asset->{$field->db_column});
|
if (Gate::allows('admin')) {
|
||||||
|
$decrypted_old = Helper::gracefulDecrypt($field, $asset->{$field->db_column});
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if the decrypted existing value is different from one we just submitted
|
|
||||||
* and if not, pull it out of the object since it shouldn't really be updating at all.
|
|
||||||
* If we don't do this, it will try to re-encrypt it, and the same value encrypted two
|
|
||||||
* different times will have different values, so it will *look* like it was updated
|
|
||||||
* but it wasn't.
|
|
||||||
*/
|
|
||||||
if ($decrypted_old != $this->update_array[$field->db_column]) {
|
|
||||||
$asset->{$field->db_column} = \Crypt::encrypt($this->update_array[$field->db_column]);
|
|
||||||
} else {
|
|
||||||
/*
|
/*
|
||||||
* Remove the encrypted custom field from the update_array, since nothing changed
|
* Check if the decrypted existing value is different from one we just submitted
|
||||||
|
* and if not, pull it out of the object since it shouldn't really be updating at all.
|
||||||
|
* If we don't do this, it will try to re-encrypt it, and the same value encrypted two
|
||||||
|
* different times will have different values, so it will *look* like it was updated
|
||||||
|
* but it wasn't.
|
||||||
*/
|
*/
|
||||||
unset($this->update_array[$field->db_column]);
|
if ($decrypted_old != $this->update_array[$field->db_column]) {
|
||||||
unset($asset->{$field->db_column});
|
$asset->{$field->db_column} = Crypt::encrypt($this->update_array[$field->db_column]);
|
||||||
}
|
} else {
|
||||||
|
/*
|
||||||
|
* Remove the encrypted custom field from the update_array, since nothing changed
|
||||||
|
*/
|
||||||
|
unset($this->update_array[$field->db_column]);
|
||||||
|
unset($asset->{$field->db_column});
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These custom fields aren't encrypted, just carry on as usual
|
* These custom fields aren't encrypted, just carry on as usual
|
||||||
*/
|
*/
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if ((array_key_exists($field->db_column, $this->update_array)) && ($asset->{$field->db_column} != $this->update_array[$field->db_column])) {
|
if ((array_key_exists($field->db_column, $this->update_array)) && ($asset->{$field->db_column} != $this->update_array[$field->db_column])) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace App\Http\Controllers\Auth;
|
|||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
|
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
class ForgotPasswordController extends Controller
|
class ForgotPasswordController extends Controller
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@@ -79,16 +79,16 @@ class ForgotPasswordController extends Controller
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
} catch(\Exception $e) {
|
} catch(\Exception $e) {
|
||||||
\Log::info('Password reset attempt: User '.$request->input('username').'failed with exception: '.$e );
|
Log::info('Password reset attempt: User '.$request->input('username').'failed with exception: '.$e );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prevent timing attack to enumerate users.
|
// Prevent timing attack to enumerate users.
|
||||||
usleep(500000 + random_int(0, 1500000));
|
usleep(500000 + random_int(0, 1500000));
|
||||||
|
|
||||||
if ($response === \Password::RESET_LINK_SENT) {
|
if ($response === \Password::RESET_LINK_SENT) {
|
||||||
\Log::info('Password reset attempt: User '.$request->input('username').' WAS found, password reset sent');
|
Log::info('Password reset attempt: User '.$request->input('username').' WAS found, password reset sent');
|
||||||
} else {
|
} else {
|
||||||
\Log::info('Password reset attempt: User matching username '.$request->input('username').' NOT FOUND or user is inactive');
|
Log::info('Password reset attempt: User matching username '.$request->input('username').' NOT FOUND or user is inactive');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ use Illuminate\Support\Carbon;
|
|||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Session;
|
use Illuminate\Support\Facades\Session;
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Redirect;
|
use Redirect;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -122,7 +122,7 @@ class LoginController extends Controller
|
|||||||
Auth::login($user);
|
Auth::login($user);
|
||||||
} else {
|
} else {
|
||||||
$username = $saml->getUsername();
|
$username = $saml->getUsername();
|
||||||
\Log::debug("SAML user '$username' could not be found in database.");
|
Log::debug("SAML user '$username' could not be found in database.");
|
||||||
$request->session()->flash('error', trans('auth/message.signin.error'));
|
$request->session()->flash('error', trans('auth/message.signin.error'));
|
||||||
$saml->clearData();
|
$saml->clearData();
|
||||||
}
|
}
|
||||||
@@ -137,7 +137,7 @@ class LoginController extends Controller
|
|||||||
$s->save();
|
$s->save();
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
\Log::debug('There was an error authenticating the SAML user: '.$e->getMessage());
|
Log::debug('There was an error authenticating the SAML user: '.$e->getMessage());
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,7 +146,7 @@ class LoginController extends Controller
|
|||||||
|
|
||||||
// Better logging
|
// Better logging
|
||||||
if (empty($samlData)) {
|
if (empty($samlData)) {
|
||||||
\Log::debug("SAML page requested, but samlData seems empty.");
|
Log::debug("SAML page requested, but samlData seems empty.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,19 +261,19 @@ class LoginController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Account sign in form processing.
|
* Account sign in form processing.
|
||||||
*
|
*
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function login(Request $request)
|
public function login(Request $request)
|
||||||
{
|
{
|
||||||
|
|
||||||
//If the environment is set to ALWAYS require SAML, return access denied
|
//If the environment is set to ALWAYS require SAML, return access denied
|
||||||
if (config('app.require_saml')) {
|
if (config('app.require_saml')) {
|
||||||
\Log::debug('require SAML is enabled in the .env - return a 403');
|
Log::debug('require SAML is enabled in the .env - return a 403');
|
||||||
return view('errors.403');
|
return view('errors.403');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Setting::getSettings()->login_common_disabled == '1') {
|
if (Setting::getSettings()->login_common_disabled == '1') {
|
||||||
\Log::debug('login_common_disabled is set to 1 - return a 403');
|
Log::debug('login_common_disabled is set to 1 - return a 403');
|
||||||
return view('errors.403');
|
return view('errors.403');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -339,7 +339,7 @@ class LoginController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Two factor enrollment page
|
* Two factor enrollment page
|
||||||
*
|
*
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function getTwoFactorEnroll()
|
public function getTwoFactorEnroll()
|
||||||
{
|
{
|
||||||
@@ -389,7 +389,7 @@ class LoginController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Two factor code form page
|
* Two factor code form page
|
||||||
*
|
*
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function getTwoFactorAuth()
|
public function getTwoFactorAuth()
|
||||||
{
|
{
|
||||||
@@ -415,7 +415,7 @@ class LoginController extends Controller
|
|||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
*
|
*
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function postTwoFactorAuth(Request $request)
|
public function postTwoFactorAuth(Request $request)
|
||||||
{
|
{
|
||||||
@@ -427,10 +427,6 @@ class LoginController extends Controller
|
|||||||
return redirect()->route('two-factor')->with('error', trans('auth/message.two_factor.code_required'));
|
return redirect()->route('two-factor')->with('error', trans('auth/message.two_factor.code_required'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! $request->has('two_factor_secret')) { // TODO this seems almost the same as above?
|
|
||||||
return redirect()->route('two-factor')->with('error', 'Two-factor code is required.');
|
|
||||||
}
|
|
||||||
|
|
||||||
$user = Auth::user();
|
$user = Auth::user();
|
||||||
$secret = $request->input('two_factor_secret');
|
$secret = $request->input('two_factor_secret');
|
||||||
|
|
||||||
@@ -439,7 +435,7 @@ class LoginController extends Controller
|
|||||||
$user->saveQuietly();
|
$user->saveQuietly();
|
||||||
$request->session()->put('2fa_authed', $user->id);
|
$request->session()->put('2fa_authed', $user->id);
|
||||||
|
|
||||||
return redirect()->route('home')->with('success', 'You are logged in!');
|
return redirect()->route('home')->with('success', trans('auth/message.signin.success'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return redirect()->route('two-factor')->with('error', trans('auth/message.two_factor.invalid_code'));
|
return redirect()->route('two-factor')->with('error', trans('auth/message.two_factor.invalid_code'));
|
||||||
@@ -451,7 +447,7 @@ class LoginController extends Controller
|
|||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
*
|
*
|
||||||
* @return Redirect
|
* @return Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function logout(Request $request)
|
public function logout(Request $request)
|
||||||
{
|
{
|
||||||
@@ -537,7 +533,7 @@ class LoginController extends Controller
|
|||||||
|
|
||||||
$minutes = round($seconds / 60);
|
$minutes = round($seconds / 60);
|
||||||
|
|
||||||
$message = \Lang::get('auth/message.throttle', ['minutes' => $minutes]);
|
$message = trans('auth/message.throttle', ['minutes' => $minutes]);
|
||||||
|
|
||||||
return redirect()->back()
|
return redirect()->back()
|
||||||
->withInput($request->only($this->username(), 'remember'))
|
->withInput($request->only($this->username(), 'remember'))
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use App\Models\Setting;
|
|||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Foundation\Auth\ResetsPasswords;
|
use Illuminate\Foundation\Auth\ResetsPasswords;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class ResetPasswordController extends Controller
|
class ResetPasswordController extends Controller
|
||||||
{
|
{
|
||||||
@@ -66,7 +66,7 @@ class ResetPasswordController extends Controller
|
|||||||
$credentials = $request->only('email', 'token');
|
$credentials = $request->only('email', 'token');
|
||||||
|
|
||||||
if (is_null($this->broker()->getUser($credentials))) {
|
if (is_null($this->broker()->getUser($credentials))) {
|
||||||
\Log::debug('Password reset form FAILED - this token is not valid.');
|
Log::debug('Password reset form FAILED - this token is not valid.');
|
||||||
return redirect()->route('password.request')->with('error', trans('passwords.token'));
|
return redirect()->route('password.request')->with('error', trans('passwords.token'));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,10 +89,10 @@ class ResetPasswordController extends Controller
|
|||||||
|
|
||||||
$request->validate($this->rules(), $request->all(), $this->validationErrorMessages());
|
$request->validate($this->rules(), $request->all(), $this->validationErrorMessages());
|
||||||
|
|
||||||
\Log::debug('Checking if '.$request->input('username').' exists');
|
Log::debug('Checking if '.$request->input('username').' exists');
|
||||||
// Check to see if the user even exists - we'll treat the response the same to prevent user sniffing
|
// Check to see if the user even exists - we'll treat the response the same to prevent user sniffing
|
||||||
if ($user = User::where('username', '=', $request->input('username'))->where('activated', '1')->whereNotNull('email')->first()) {
|
if ($user = User::where('username', '=', $request->input('username'))->where('activated', '1')->whereNotNull('email')->first()) {
|
||||||
\Log::debug($user->username.' exists');
|
Log::debug($user->username.' exists');
|
||||||
|
|
||||||
|
|
||||||
// handle the password validation rules set by the admin settings
|
// handle the password validation rules set by the admin settings
|
||||||
@@ -112,17 +112,17 @@ class ResetPasswordController extends Controller
|
|||||||
|
|
||||||
// Check if the password reset above actually worked
|
// Check if the password reset above actually worked
|
||||||
if ($response == \Password::PASSWORD_RESET) {
|
if ($response == \Password::PASSWORD_RESET) {
|
||||||
\Log::debug('Password reset for '.$user->username.' worked');
|
Log::debug('Password reset for '.$user->username.' worked');
|
||||||
return redirect()->guest('login')->with('success', trans('passwords.reset'));
|
return redirect()->guest('login')->with('success', trans('passwords.reset'));
|
||||||
}
|
}
|
||||||
|
|
||||||
\Log::debug('Password reset for '.$user->username.' FAILED - this user exists but the token is not valid');
|
Log::debug('Password reset for '.$user->username.' FAILED - this user exists but the token is not valid');
|
||||||
return redirect()->back()->withInput($request->only('email'))->with('success', trans('passwords.reset'));
|
return redirect()->back()->withInput($request->only('email'))->with('success', trans('passwords.reset'));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
\Log::debug('Password reset for '.$request->input('username').' FAILED - user does not exist or does not have an email address - but make it look like it succeeded');
|
Log::debug('Password reset for '.$request->input('username').' FAILED - user does not exist or does not have an email address - but make it look like it succeeded');
|
||||||
return redirect()->guest('login')->with('success', trans('passwords.reset'));
|
return redirect()->guest('login')->with('success', trans('passwords.reset'));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace App\Http\Controllers\Auth;
|
|||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Services\Saml;
|
use App\Services\Saml;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This controller provides the endpoint for SAML communication and metadata.
|
* This controller provides the endpoint for SAML communication and metadata.
|
||||||
@@ -51,7 +51,7 @@ class SamlController extends Controller
|
|||||||
$metadata = $this->saml->getSPMetadata();
|
$metadata = $this->saml->getSPMetadata();
|
||||||
|
|
||||||
if (empty($metadata)) {
|
if (empty($metadata)) {
|
||||||
\Log::debug('SAML metadata is empty - return a 403');
|
Log::debug('SAML metadata is empty - return a 403');
|
||||||
return response()->view('errors.403', [], 403);
|
return response()->view('errors.403', [], 403);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ class SamlController extends Controller
|
|||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
*
|
*
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function login(Request $request)
|
public function login(Request $request)
|
||||||
{
|
{
|
||||||
@@ -93,7 +93,7 @@ class SamlController extends Controller
|
|||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
*
|
*
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function acs(Request $request)
|
public function acs(Request $request)
|
||||||
{
|
{
|
||||||
@@ -126,7 +126,7 @@ class SamlController extends Controller
|
|||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
*
|
*
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function sls(Request $request)
|
public function sls(Request $request)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ class BulkAssetModelsController extends Controller
|
|||||||
*
|
*
|
||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @since [v1.0]
|
* @since [v1.0]
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function destroy(Request $request)
|
public function destroy(Request $request)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace App\Http\Controllers;
|
|||||||
use App\Helpers\Helper;
|
use App\Helpers\Helper;
|
||||||
use App\Http\Requests\ImageUploadRequest;
|
use App\Http\Requests\ImageUploadRequest;
|
||||||
use App\Models\Category as Category;
|
use App\Models\Category as Category;
|
||||||
use Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Str;
|
use Str;
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use App\Http\Requests\ImageUploadRequest;
|
|||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This controller handles all actions related to Companies for
|
* This controller handles all actions related to Companies for
|
||||||
@@ -154,7 +155,7 @@ final class CompaniesController extends Controller
|
|||||||
try {
|
try {
|
||||||
Storage::disk('public')->delete('companies'.'/'.$company->image);
|
Storage::disk('public')->delete('companies'.'/'.$company->image);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
\Log::debug($e);
|
Log::debug($e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ use Illuminate\Support\Facades\Auth;
|
|||||||
use Illuminate\Support\Facades\Input;
|
use Illuminate\Support\Facades\Input;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class controls all actions related to Components for
|
* This class controls all actions related to Components for
|
||||||
@@ -188,7 +189,7 @@ class ComponentsController extends Controller
|
|||||||
try {
|
try {
|
||||||
Storage::disk('public')->delete('components/'.$component->image);
|
Storage::disk('public')->delete('components/'.$component->image);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
\Log::debug($e);
|
Log::debug($e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use App\Models\Component;
|
|||||||
use Illuminate\Support\Facades\Response;
|
use Illuminate\Support\Facades\Response;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class ComponentsFilesController extends Controller
|
class ComponentsFilesController extends Controller
|
||||||
{
|
{
|
||||||
@@ -84,7 +85,7 @@ class ComponentsFilesController extends Controller
|
|||||||
try {
|
try {
|
||||||
Storage::delete('components/'.$log->filename);
|
Storage::delete('components/'.$log->filename);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
\Log::debug($e);
|
Log::debug($e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,7 +111,7 @@ class ComponentsFilesController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function show($componentId = null, $fileId = null)
|
public function show($componentId = null, $fileId = null)
|
||||||
{
|
{
|
||||||
\Log::debug('Private filesystem is: '.config('filesystems.default'));
|
Log::debug('Private filesystem is: '.config('filesystems.default'));
|
||||||
$component = Component::find($componentId);
|
$component = Component::find($componentId);
|
||||||
|
|
||||||
// the component is valid
|
// the component is valid
|
||||||
@@ -126,8 +127,8 @@ class ComponentsFilesController extends Controller
|
|||||||
$file = 'private_uploads/components/'.$log->filename;
|
$file = 'private_uploads/components/'.$log->filename;
|
||||||
|
|
||||||
if (Storage::missing($file)) {
|
if (Storage::missing($file)) {
|
||||||
\Log::debug('FILE DOES NOT EXISTS for '.$file);
|
Log::debug('FILE DOES NOT EXISTS for '.$file);
|
||||||
\Log::debug('URL should be '.Storage::url($file));
|
Log::debug('URL should be '.Storage::url($file));
|
||||||
|
|
||||||
return response('File '.$file.' ('.Storage::url($file).') not found on server', 404)
|
return response('File '.$file.' ('.Storage::url($file).') not found on server', 404)
|
||||||
->header('Content-Type', 'text/plain');
|
->header('Content-Type', 'text/plain');
|
||||||
|
|||||||
@@ -71,8 +71,14 @@ class ConsumableCheckoutController extends Controller
|
|||||||
|
|
||||||
$this->authorize('checkout', $consumable);
|
$this->authorize('checkout', $consumable);
|
||||||
|
|
||||||
|
// If the quantity is not present in the request or is not a positive integer, set it to 1
|
||||||
|
$quantity = $request->input('qty');
|
||||||
|
if (!isset($quantity) || !ctype_digit((string)$quantity) || $quantity <= 0) {
|
||||||
|
$quantity = 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure there is at least one available to checkout
|
// Make sure there is at least one available to checkout
|
||||||
if ($consumable->numRemaining() <= 0) {
|
if ($consumable->numRemaining() <= 0 || $quantity > $consumable->numRemaining()) {
|
||||||
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.checkout.unavailable'));
|
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.checkout.unavailable'));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,13 +94,14 @@ class ConsumableCheckoutController extends Controller
|
|||||||
// Update the consumable data
|
// Update the consumable data
|
||||||
$consumable->assigned_to = e($request->input('assigned_to'));
|
$consumable->assigned_to = e($request->input('assigned_to'));
|
||||||
|
|
||||||
|
for($i = 0; $i < $quantity; $i++){
|
||||||
$consumable->users()->attach($consumable->id, [
|
$consumable->users()->attach($consumable->id, [
|
||||||
'consumable_id' => $consumable->id,
|
'consumable_id' => $consumable->id,
|
||||||
'user_id' => $admin_user->id,
|
'user_id' => $admin_user->id,
|
||||||
'assigned_to' => e($request->input('assigned_to')),
|
'assigned_to' => e($request->input('assigned_to')),
|
||||||
'note' => $request->input('note'),
|
'note' => $request->input('note'),
|
||||||
]);
|
]);
|
||||||
|
}
|
||||||
event(new CheckoutableCheckedOut($consumable, $user, Auth::user(), $request->input('note')));
|
event(new CheckoutableCheckedOut($consumable, $user, Auth::user(), $request->input('note')));
|
||||||
|
|
||||||
// Redirect to the new consumable page
|
// Redirect to the new consumable page
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use App\Models\Consumable;
|
|||||||
use Illuminate\Support\Facades\Response;
|
use Illuminate\Support\Facades\Response;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Symfony\Consumable\HttpFoundation\JsonResponse;
|
use Symfony\Consumable\HttpFoundation\JsonResponse;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
class ConsumablesFilesController extends Controller
|
class ConsumablesFilesController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@@ -83,7 +83,7 @@ class ConsumablesFilesController extends Controller
|
|||||||
try {
|
try {
|
||||||
Storage::delete('consumables/'.$log->filename);
|
Storage::delete('consumables/'.$log->filename);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
\Log::debug($e);
|
Log::debug($e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,8 +124,8 @@ class ConsumablesFilesController extends Controller
|
|||||||
$file = 'private_uploads/consumables/'.$log->filename;
|
$file = 'private_uploads/consumables/'.$log->filename;
|
||||||
|
|
||||||
if (Storage::missing($file)) {
|
if (Storage::missing($file)) {
|
||||||
\Log::debug('FILE DOES NOT EXISTS for '.$file);
|
Log::debug('FILE DOES NOT EXISTS for '.$file);
|
||||||
\Log::debug('URL should be '.Storage::url($file));
|
Log::debug('URL should be '.Storage::url($file));
|
||||||
|
|
||||||
return response('File '.$file.' ('.Storage::url($file).') not found on server', 404)
|
return response('File '.$file.' ('.Storage::url($file).') not found on server', 404)
|
||||||
->header('Content-Type', 'text/plain');
|
->header('Content-Type', 'text/plain');
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ use App\Models\CustomField;
|
|||||||
use App\Models\CustomFieldset;
|
use App\Models\CustomFieldset;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Redirect;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This controller handles all actions related to Custom Asset Fields for
|
* This controller handles all actions related to Custom Asset Fields for
|
||||||
@@ -260,7 +259,7 @@ class CustomFieldsController extends Controller
|
|||||||
|
|
||||||
$field->name = trim(e($request->get("name")));
|
$field->name = trim(e($request->get("name")));
|
||||||
$field->element = e($request->get("element"));
|
$field->element = e($request->get("element"));
|
||||||
$field->field_values = e($request->get("field_values"));
|
$field->field_values = $request->get("field_values");
|
||||||
$field->user_id = Auth::id();
|
$field->user_id = Auth::id();
|
||||||
$field->help_text = $request->get("help_text");
|
$field->help_text = $request->get("help_text");
|
||||||
$field->show_in_email = $show_in_email;
|
$field->show_in_email = $show_in_email;
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ class CustomFieldsetsController extends Controller
|
|||||||
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
|
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
|
||||||
* @since [v1.8]
|
* @since [v1.8]
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
*/
|
*/
|
||||||
public function store(Request $request)
|
public function store(Request $request)
|
||||||
@@ -126,7 +126,7 @@ class CustomFieldsetsController extends Controller
|
|||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @param int $id
|
* @param int $id
|
||||||
* @since [v6.0.14]
|
* @since [v6.0.14]
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
*/
|
*/
|
||||||
public function edit($id)
|
public function edit($id)
|
||||||
@@ -147,7 +147,7 @@ class CustomFieldsetsController extends Controller
|
|||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @param int $id
|
* @param int $id
|
||||||
* @since [v6.0.14]
|
* @since [v6.0.14]
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
*/
|
*/
|
||||||
public function update(Request $request, $id)
|
public function update(Request $request, $id)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use App\Models\Department;
|
|||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class DepartmentsController extends Controller
|
class DepartmentsController extends Controller
|
||||||
{
|
{
|
||||||
@@ -129,7 +130,7 @@ class DepartmentsController extends Controller
|
|||||||
try {
|
try {
|
||||||
Storage::disk('public')->delete('departments'.'/'.$department->image);
|
Storage::disk('public')->delete('departments'.'/'.$department->image);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
\Log::debug($e);
|
Log::debug($e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$department->delete();
|
$department->delete();
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use Illuminate\Support\Facades\Auth;
|
|||||||
use Laravel\Socialite\Facades\Socialite;
|
use Laravel\Socialite\Facades\Socialite;
|
||||||
use Laravel\Socialite\Two\InvalidStateException;
|
use Laravel\Socialite\Two\InvalidStateException;
|
||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class GoogleAuthController extends Controller
|
class GoogleAuthController extends Controller
|
||||||
{
|
{
|
||||||
@@ -34,9 +34,9 @@ class GoogleAuthController extends Controller
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$socialUser = Socialite::driver('google')->user();
|
$socialUser = Socialite::driver('google')->user();
|
||||||
\Log::debug('Google user found in Google Workspace');
|
Log::debug('Google user found in Google Workspace');
|
||||||
} catch (InvalidStateException $exception) {
|
} catch (InvalidStateException $exception) {
|
||||||
\Log::debug('Google user NOT found in Google Workspace');
|
Log::debug('Google user NOT found in Google Workspace');
|
||||||
return redirect()->route('login')
|
return redirect()->route('login')
|
||||||
->withErrors(
|
->withErrors(
|
||||||
[
|
[
|
||||||
@@ -52,7 +52,7 @@ class GoogleAuthController extends Controller
|
|||||||
|
|
||||||
|
|
||||||
if ($user) {
|
if ($user) {
|
||||||
\Log::debug('Google user '.$socialUser->getEmail().' found in Snipe-IT');
|
Log::debug('Google user '.$socialUser->getEmail().' found in Snipe-IT');
|
||||||
$user->update([
|
$user->update([
|
||||||
'avatar' => $socialUser->avatar,
|
'avatar' => $socialUser->avatar,
|
||||||
]);
|
]);
|
||||||
@@ -61,7 +61,7 @@ class GoogleAuthController extends Controller
|
|||||||
return redirect()->route('home');
|
return redirect()->route('home');
|
||||||
}
|
}
|
||||||
|
|
||||||
\Log::debug('Google user '.$socialUser->getEmail().' NOT found in Snipe-IT');
|
Log::debug('Google user '.$socialUser->getEmail().' NOT found in Snipe-IT');
|
||||||
return redirect()->route('login')
|
return redirect()->route('login')
|
||||||
->withErrors(
|
->withErrors(
|
||||||
[
|
[
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace App\Http\Controllers;
|
|||||||
use App\Helpers\Helper;
|
use App\Helpers\Helper;
|
||||||
use App\Models\Group;
|
use App\Models\Group;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This controller handles all actions related to User Groups for
|
* This controller handles all actions related to User Groups for
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ class CheckoutKitController extends Controller
|
|||||||
* Validate and process the new Predefined Kit data.
|
* Validate and process the new Predefined Kit data.
|
||||||
*
|
*
|
||||||
* @author [D. Minaev.] [<dmitriy.minaev.v@gmail.com>]
|
* @author [D. Minaev.] [<dmitriy.minaev.v@gmail.com>]
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function store(Request $request, $kit_id)
|
public function store(Request $request, $kit_id)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class PredefinedKitsController extends Controller
|
|||||||
* Validate and process the new Predefined Kit data.
|
* Validate and process the new Predefined Kit data.
|
||||||
*
|
*
|
||||||
* @author [D. Minaev] [<dmitriy.minaev.v@gmail.com>]
|
* @author [D. Minaev] [<dmitriy.minaev.v@gmail.com>]
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function store(ImageUploadRequest $request)
|
public function store(ImageUploadRequest $request)
|
||||||
{
|
{
|
||||||
@@ -95,7 +95,7 @@ class PredefinedKitsController extends Controller
|
|||||||
* @author [D. Minaev] [<dmitriy.minaev.v@gmail.com>]
|
* @author [D. Minaev] [<dmitriy.minaev.v@gmail.com>]
|
||||||
* @since [v1.0]
|
* @since [v1.0]
|
||||||
* @param int $kit_id
|
* @param int $kit_id
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function update(ImageUploadRequest $request, $kit_id = null)
|
public function update(ImageUploadRequest $request, $kit_id = null)
|
||||||
{
|
{
|
||||||
@@ -122,7 +122,7 @@ class PredefinedKitsController extends Controller
|
|||||||
* @author [D. Minaev] [<dmitriy.minaev.v@gmail.com>]
|
* @author [D. Minaev] [<dmitriy.minaev.v@gmail.com>]
|
||||||
* @since [v1.0]
|
* @since [v1.0]
|
||||||
* @param int $kit_id
|
* @param int $kit_id
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function destroy($kit_id)
|
public function destroy($kit_id)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ use App\Models\Setting;
|
|||||||
use App\Models\Supplier;
|
use App\Models\Supplier;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\View\Label as LabelView;
|
use App\View\Label as LabelView;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
class LabelsController extends Controller
|
class LabelsController extends Controller
|
||||||
@@ -21,9 +22,9 @@ class LabelsController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Returns the Label view with test data
|
* Returns the Label view with test data
|
||||||
*
|
*
|
||||||
* @author Grant Le Roux <grant.leroux+snipe-it@gmail.com>
|
* @param string $labelName
|
||||||
* @param string $labelName
|
|
||||||
* @return \Illuminate\Contracts\View\View
|
* @return \Illuminate\Contracts\View\View
|
||||||
|
* @author Grant Le Roux <grant.leroux+snipe-it@gmail.com>
|
||||||
*/
|
*/
|
||||||
public function show(string $labelName)
|
public function show(string $labelName)
|
||||||
{
|
{
|
||||||
@@ -66,16 +67,18 @@ class LabelsController extends Controller
|
|||||||
$exampleAsset->model->category->id = 999999;
|
$exampleAsset->model->category->id = 999999;
|
||||||
$exampleAsset->model->category->name = trans('admin/labels/table.example_category');
|
$exampleAsset->model->category->name = trans('admin/labels/table.example_category');
|
||||||
|
|
||||||
$customFieldColumns = CustomField::all()->pluck('db_column');
|
$customFieldColumns = CustomField::where('field_encrypted', '=', 0)->pluck('db_column');
|
||||||
|
|
||||||
collect(explode(';', Setting::getSettings()->label2_fields))
|
collect(explode(';', Setting::getSettings()->label2_fields))
|
||||||
->filter()
|
->filter()
|
||||||
->each(function ($item) use ($customFieldColumns, $exampleAsset) {
|
->each(function ($item) use ($customFieldColumns, $exampleAsset) {
|
||||||
$pair = explode('=', $item);
|
$pair = explode('=', $item);
|
||||||
|
|
||||||
if ($customFieldColumns->contains($pair[1])) {
|
if (array_key_exists(1, $pair)) {
|
||||||
$exampleAsset->{$pair[1]} = "{{$pair[0]}}";
|
if ($customFieldColumns->contains($pair[1])) {
|
||||||
}
|
$exampleAsset->{$pair[1]} = "{{$pair[0]}}";
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$settings = Setting::getSettings();
|
$settings = Setting::getSettings();
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ use Illuminate\Support\Facades\Auth;
|
|||||||
use Illuminate\Support\Facades\Input;
|
use Illuminate\Support\Facades\Input;
|
||||||
use Illuminate\Support\Facades\Session;
|
use Illuminate\Support\Facades\Session;
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class LicenseCheckinController extends Controller
|
class LicenseCheckinController extends Controller
|
||||||
{
|
{
|
||||||
@@ -145,7 +146,7 @@ class LicenseCheckinController extends Controller
|
|||||||
$user_seat->assigned_to = null;
|
$user_seat->assigned_to = null;
|
||||||
|
|
||||||
if ($user_seat->save()) {
|
if ($user_seat->save()) {
|
||||||
\Log::debug('Checking in '.$license->name.' from user '.$user_seat->username);
|
Log::debug('Checking in '.$license->name.' from user '.$user_seat->username);
|
||||||
$user_seat->logCheckin($user_seat->user, trans('admin/licenses/general.bulk.checkin_all.log_msg'));
|
$user_seat->logCheckin($user_seat->user, trans('admin/licenses/general.bulk.checkin_all.log_msg'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -160,7 +161,7 @@ class LicenseCheckinController extends Controller
|
|||||||
$asset_seat->asset_id = null;
|
$asset_seat->asset_id = null;
|
||||||
|
|
||||||
if ($asset_seat->save()) {
|
if ($asset_seat->save()) {
|
||||||
\Log::debug('Checking in '.$license->name.' from asset '.$asset_seat->asset_tag);
|
Log::debug('Checking in '.$license->name.' from asset '.$asset_seat->asset_tag);
|
||||||
$asset_seat->logCheckin($asset_seat->asset, trans('admin/licenses/general.bulk.checkin_all.log_msg'));
|
$asset_seat->logCheckin($asset_seat->asset, trans('admin/licenses/general.bulk.checkin_all.log_msg'));
|
||||||
$count++;
|
$count++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ use App\Models\License;
|
|||||||
use App\Models\LicenseSeat;
|
use App\Models\LicenseSeat;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class LicenseCheckoutController extends Controller
|
class LicenseCheckoutController extends Controller
|
||||||
{
|
{
|
||||||
@@ -155,16 +156,16 @@ class LicenseCheckoutController extends Controller
|
|||||||
|
|
||||||
public function bulkCheckout($licenseId) {
|
public function bulkCheckout($licenseId) {
|
||||||
|
|
||||||
\Log::debug('Checking out '.$licenseId.' via bulk');
|
Log::debug('Checking out '.$licenseId.' via bulk');
|
||||||
$license = License::findOrFail($licenseId);
|
$license = License::findOrFail($licenseId);
|
||||||
$this->authorize('checkin', $license);
|
$this->authorize('checkin', $license);
|
||||||
$avail_count = $license->getAvailSeatsCountAttribute();
|
$avail_count = $license->getAvailSeatsCountAttribute();
|
||||||
|
|
||||||
$users = User::whereNull('deleted_at')->where('autoassign_licenses', '=', 1)->with('licenses')->get();
|
$users = User::whereNull('deleted_at')->where('autoassign_licenses', '=', 1)->with('licenses')->get();
|
||||||
\Log::debug($avail_count.' will be assigned');
|
Log::debug($avail_count.' will be assigned');
|
||||||
|
|
||||||
if ($users->count() > $avail_count) {
|
if ($users->count() > $avail_count) {
|
||||||
\Log::debug('You do not have enough free seats to complete this task, so we will check out as many as we can. ');
|
Log::debug('You do not have enough free seats to complete this task, so we will check out as many as we can. ');
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the license is valid, check that there is an available seat
|
// If the license is valid, check that there is an available seat
|
||||||
@@ -179,7 +180,7 @@ class LicenseCheckoutController extends Controller
|
|||||||
|
|
||||||
// Check to make sure this user doesn't already have this license checked out to them
|
// Check to make sure this user doesn't already have this license checked out to them
|
||||||
if ($user->licenses->where('id', '=', $licenseId)->count()) {
|
if ($user->licenses->where('id', '=', $licenseId)->count()) {
|
||||||
\Log::debug($user->username.' already has this license checked out to them. Skipping... ');
|
Log::debug($user->username.' already has this license checked out to them. Skipping... ');
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,7 +193,7 @@ class LicenseCheckoutController extends Controller
|
|||||||
$avail_count--;
|
$avail_count--;
|
||||||
$assigned_count++;
|
$assigned_count++;
|
||||||
$licenseSeat->logCheckout(trans('admin/licenses/general.bulk.checkout_all.log_msg'), $user);
|
$licenseSeat->logCheckout(trans('admin/licenses/general.bulk.checkout_all.log_msg'), $user);
|
||||||
\Log::debug('License '.$license->name.' seat '.$licenseSeat->id.' checked out to '.$user->username);
|
Log::debug('License '.$license->name.' seat '.$licenseSeat->id.' checked out to '.$user->username);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($avail_count == 0) {
|
if ($avail_count == 0) {
|
||||||
|
|||||||
@@ -7,9 +7,8 @@ use App\Http\Controllers\Controller;
|
|||||||
use App\Http\Requests\UploadFileRequest;
|
use App\Http\Requests\UploadFileRequest;
|
||||||
use App\Models\Actionlog;
|
use App\Models\Actionlog;
|
||||||
use App\Models\License;
|
use App\Models\License;
|
||||||
use Illuminate\Support\Facades\Response;
|
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class LicenseFilesController extends Controller
|
class LicenseFilesController extends Controller
|
||||||
{
|
{
|
||||||
@@ -20,7 +19,7 @@ class LicenseFilesController extends Controller
|
|||||||
* @param int $licenseId
|
* @param int $licenseId
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
*@author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @since [v1.0]
|
* @since [v1.0]
|
||||||
* @todo Switch to using the AssetFileRequest form request validator.
|
* @todo Switch to using the AssetFileRequest form request validator.
|
||||||
*/
|
*/
|
||||||
@@ -78,7 +77,7 @@ class LicenseFilesController extends Controller
|
|||||||
try {
|
try {
|
||||||
Storage::delete('licenses/'.$log->filename);
|
Storage::delete('licenses/'.$log->filename);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
\Log::debug($e);
|
Log::debug($e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,8 +120,8 @@ class LicenseFilesController extends Controller
|
|||||||
$file = 'private_uploads/licenses/'.$log->filename;
|
$file = 'private_uploads/licenses/'.$log->filename;
|
||||||
|
|
||||||
if (Storage::missing($file)) {
|
if (Storage::missing($file)) {
|
||||||
\Log::debug('NOT EXISTS for '.$file);
|
Log::debug('NOT EXISTS for '.$file);
|
||||||
\Log::debug('NOT EXISTS URL should be '.Storage::url($file));
|
Log::debug('NOT EXISTS URL should be '.Storage::url($file));
|
||||||
|
|
||||||
return response('File '.$file.' ('.Storage::url($file).') not found on server', 404)
|
return response('File '.$file.' ('.Storage::url($file).') not found on server', 404)
|
||||||
->header('Content-Type', 'text/plain');
|
->header('Content-Type', 'text/plain');
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ use App\Models\User;
|
|||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This controller handles all actions related to Licenses for
|
* This controller handles all actions related to Licenses for
|
||||||
@@ -289,4 +290,106 @@ class LicensesController extends Controller
|
|||||||
->with('item', $license)
|
->with('item', $license)
|
||||||
->with('maintained_list', $maintained_list);
|
->with('maintained_list', $maintained_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exports Licenses to CSV
|
||||||
|
*
|
||||||
|
* @author [G. Martinez]
|
||||||
|
* @since [v6.3]
|
||||||
|
* @return StreamedResponse
|
||||||
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
|
*/
|
||||||
|
public function getExportLicensesCsv()
|
||||||
|
{
|
||||||
|
$this->authorize('view', License::class);
|
||||||
|
\Debugbar::disable();
|
||||||
|
|
||||||
|
$response = new StreamedResponse(function () {
|
||||||
|
// Open output stream
|
||||||
|
$handle = fopen('php://output', 'w');
|
||||||
|
$licenses= License::with('company',
|
||||||
|
'manufacturer',
|
||||||
|
'category',
|
||||||
|
'supplier',
|
||||||
|
'adminuser',
|
||||||
|
'assignedusers')
|
||||||
|
->orderBy('created_at', 'DESC');
|
||||||
|
Company::scopeCompanyables($licenses)
|
||||||
|
->chunk(500, function ($licenses) use ($handle) {
|
||||||
|
$headers = [
|
||||||
|
// strtolower to prevent Excel from trying to open it as a SYLK file
|
||||||
|
strtolower(trans('general.id')),
|
||||||
|
trans('general.company'),
|
||||||
|
trans('general.name'),
|
||||||
|
trans('general.serial_number'),
|
||||||
|
trans('general.purchase_date'),
|
||||||
|
trans('general.purchase_cost'),
|
||||||
|
trans('general.order_number'),
|
||||||
|
trans('general.licenses_available'),
|
||||||
|
trans('admin/licenses/table.seats'),
|
||||||
|
trans('general.created_by'),
|
||||||
|
trans('general.depreciation'),
|
||||||
|
trans('general.updated_at'),
|
||||||
|
trans('admin/licenses/table.deleted_at'),
|
||||||
|
trans('general.email'),
|
||||||
|
trans('admin/hardware/form.fully_depreciated'),
|
||||||
|
trans('general.supplier'),
|
||||||
|
trans('admin/licenses/form.expiration'),
|
||||||
|
trans('admin/licenses/form.purchase_order'),
|
||||||
|
trans('admin/licenses/form.termination_date'),
|
||||||
|
trans('admin/licenses/form.maintained'),
|
||||||
|
trans('general.manufacturer'),
|
||||||
|
trans('general.category'),
|
||||||
|
trans('general.min_amt'),
|
||||||
|
trans('admin/licenses/form.reassignable'),
|
||||||
|
trans('general.notes'),
|
||||||
|
trans('general.created_at'),
|
||||||
|
];
|
||||||
|
|
||||||
|
fputcsv($handle, $headers);
|
||||||
|
|
||||||
|
foreach ($licenses as $license) {
|
||||||
|
// Add a new row with data
|
||||||
|
$values = [
|
||||||
|
$license->id,
|
||||||
|
$license->company ? $license->company->name: '',
|
||||||
|
$license->name,
|
||||||
|
$license->serial,
|
||||||
|
$license->purchase_date,
|
||||||
|
$license->purchase_cost,
|
||||||
|
$license->order_number,
|
||||||
|
$license->free_seat_count,
|
||||||
|
$license->seats,
|
||||||
|
($license->adminuser ? $license->adminuser->present()->fullName() : trans('admin/reports/general.deleted_user')),
|
||||||
|
$license->depreciation ? $license->depreciation->name: '',
|
||||||
|
$license->updated_at,
|
||||||
|
$license->deleted_at,
|
||||||
|
$license->email,
|
||||||
|
( $license->depreciate == '1') ? trans('general.yes') : trans('general.no'),
|
||||||
|
($license->supplier) ? $license->supplier->name: '',
|
||||||
|
$license->expiration_date,
|
||||||
|
$license->purchase_order,
|
||||||
|
$license->termination_date,
|
||||||
|
( $license->maintained == '1') ? trans('general.yes') : trans('general.no'),
|
||||||
|
$license->manufacturer ? $license->manufacturer->name: '',
|
||||||
|
$license->category ? $license->category->name: '',
|
||||||
|
$license->min_amt,
|
||||||
|
( $license->reassignable == '1') ? trans('general.yes') : trans('general.no'),
|
||||||
|
$license->notes,
|
||||||
|
$license->created_at,
|
||||||
|
];
|
||||||
|
|
||||||
|
fputcsv($handle, $values);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Close the output stream
|
||||||
|
fclose($handle);
|
||||||
|
}, 200, [
|
||||||
|
'Content-Type' => 'text/csv; charset=UTF-8',
|
||||||
|
'Content-Disposition' => 'attachment; filename="licenses-'.date('Y-m-d-his').'.csv"',
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ use App\Models\User;
|
|||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This controller handles all actions related to Locations for
|
* This controller handles all actions related to Locations for
|
||||||
@@ -186,7 +187,7 @@ class LocationsController extends Controller
|
|||||||
try {
|
try {
|
||||||
Storage::disk('public')->delete('locations/'.$location->image);
|
Storage::disk('public')->delete('locations/'.$location->image);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
\Log::error($e);
|
Log::error($e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$location->delete();
|
$location->delete();
|
||||||
@@ -320,7 +321,12 @@ class LocationsController extends Controller
|
|||||||
$locations_raw_array = $request->input('ids');
|
$locations_raw_array = $request->input('ids');
|
||||||
|
|
||||||
if ((is_array($locations_raw_array)) && (count($locations_raw_array) > 0)) {
|
if ((is_array($locations_raw_array)) && (count($locations_raw_array) > 0)) {
|
||||||
$locations = Location::whereIn('id', $locations_raw_array)->get();
|
$locations = Location::whereIn('id', $locations_raw_array)
|
||||||
|
->withCount('assignedAssets as assigned_assets_count')
|
||||||
|
->withCount('assets as assets_count')
|
||||||
|
->withCount('rtd_assets as rtd_assets_count')
|
||||||
|
->withCount('children as children_count')
|
||||||
|
->withCount('users as users_count')->get();
|
||||||
|
|
||||||
$success_count = 0;
|
$success_count = 0;
|
||||||
$error_count = 0;
|
$error_count = 0;
|
||||||
@@ -336,8 +342,8 @@ class LocationsController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
\Log::debug('Success count: '.$success_count);
|
Log::debug('Success count: '.$success_count);
|
||||||
\Log::debug('Error count: '.$error_count);
|
Log::debug('Error count: '.$error_count);
|
||||||
// Complete success
|
// Complete success
|
||||||
if ($success_count == count($locations_raw_array)) {
|
if ($success_count == count($locations_raw_array)) {
|
||||||
return redirect()
|
return redirect()
|
||||||
@@ -351,7 +357,7 @@ class LocationsController extends Controller
|
|||||||
if ($error_count > 0) {
|
if ($error_count > 0) {
|
||||||
return redirect()
|
return redirect()
|
||||||
->route('locations.index')
|
->route('locations.index')
|
||||||
->with('warning', trans('general.bulk.partial_success',
|
->with('warning', trans('general.bulk.delete.partial',
|
||||||
['success' => $success_count, 'error' => $error_count, 'object_type' => trans('general.locations')]
|
['success' => $success_count, 'error' => $error_count, 'object_type' => trans('general.locations')]
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ use Illuminate\Http\Request;
|
|||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Redirect;
|
use Redirect;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This controller handles all actions related to Manufacturers for
|
* This controller handles all actions related to Manufacturers for
|
||||||
@@ -174,7 +175,7 @@ class ManufacturersController extends Controller
|
|||||||
try {
|
try {
|
||||||
Storage::disk('public')->delete('manufacturers/'.$manufacturer->image);
|
Storage::disk('public')->delete('manufacturers/'.$manufacturer->image);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
\Log::info($e);
|
Log::info($e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,7 +220,7 @@ class ManufacturersController extends Controller
|
|||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @since [v4.1.15]
|
* @since [v4.1.15]
|
||||||
* @param int $manufacturers_id
|
* @param int $manufacturers_id
|
||||||
* @return Redirect
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
*/
|
*/
|
||||||
public function restore($id)
|
public function restore($id)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user