Compare commits
16 Commits
58f077950c
...
4225d51140
Author | SHA1 | Date | |
---|---|---|---|
|
4225d51140 | ||
|
dff6905050 | ||
|
d02c580d1b | ||
|
568332e502 | ||
|
4e373b1005 | ||
|
840686bfff | ||
|
2d7600eb6f | ||
|
c35d9e942f | ||
|
5aea67214a | ||
|
31204d4327 | ||
|
220fc48b35 | ||
|
aa0305d1cb | ||
|
36ef372726 | ||
|
c05c0d8f75 | ||
|
431700a888 | ||
|
b8d73e3a94 |
1
globals.d.ts
vendored
Normal file
1
globals.d.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
declare module 'net-snmp'
|
790
package-lock.json
generated
790
package-lock.json
generated
|
@ -1,20 +1,22 @@
|
|||
{
|
||||
"name": "ifms-healthtracker",
|
||||
"name": "ifms-printer-manager",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "ifms-healthtracker",
|
||||
"name": "ifms-printer-manager",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@prisma/client": "^4.15.0",
|
||||
"body-parser": "^1.20.2",
|
||||
"bree": "^9.1.3",
|
||||
"dotenv": "^16.1.4",
|
||||
"express": "^4.18.2",
|
||||
"jsonwebtoken": "^9.0.0",
|
||||
"ldapts": "^4.2.6"
|
||||
"ldapts": "^4.2.6",
|
||||
"net-snmp": "^3.9.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/express": "^4.17.17",
|
||||
|
@ -24,9 +26,29 @@
|
|||
"prisma": "^4.15.0",
|
||||
"rimraf": "^5.0.1",
|
||||
"ts-node": "^10.9.1",
|
||||
"tsx": "^3.12.7",
|
||||
"typescript": "^5.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/runtime": {
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.5.tgz",
|
||||
"integrity": "sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==",
|
||||
"dependencies": {
|
||||
"regenerator-runtime": "^0.13.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@breejs/later": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@breejs/later/-/later-4.1.0.tgz",
|
||||
"integrity": "sha512-QgGnZ9b7o4k0Ai1ZbTJWwZpZcFK9d+Gb+DyNt4UT9x6IEIs5HVu0iIlmgzGqN+t9MoJSpSPo9S/Mm51UtHr3JA==",
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@cspotcode/source-map-support": {
|
||||
"version": "0.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
|
||||
|
@ -39,6 +61,388 @@
|
|||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild-kit/cjs-loader": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild-kit/cjs-loader/-/cjs-loader-2.4.2.tgz",
|
||||
"integrity": "sha512-BDXFbYOJzT/NBEtp71cvsrGPwGAMGRB/349rwKuoxNSiKjPraNNnlK6MIIabViCjqZugu6j+xeMDlEkWdHHJSg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@esbuild-kit/core-utils": "^3.0.0",
|
||||
"get-tsconfig": "^4.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild-kit/core-utils": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild-kit/core-utils/-/core-utils-3.1.0.tgz",
|
||||
"integrity": "sha512-Uuk8RpCg/7fdHSceR1M6XbSZFSuMrxcePFuGgyvsBn+u339dk5OeL4jv2EojwTN2st/unJGsVm4qHWjWNmJ/tw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"esbuild": "~0.17.6",
|
||||
"source-map-support": "^0.5.21"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild-kit/esm-loader": {
|
||||
"version": "2.5.5",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild-kit/esm-loader/-/esm-loader-2.5.5.tgz",
|
||||
"integrity": "sha512-Qwfvj/qoPbClxCRNuac1Du01r9gvNOT+pMYtJDapfB1eoGN1YlJ1BixLyL9WVENRx5RXgNLdfYdx/CuswlGhMw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@esbuild-kit/core-utils": "^3.0.0",
|
||||
"get-tsconfig": "^4.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz",
|
||||
"integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz",
|
||||
"integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-x64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz",
|
||||
"integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-arm64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz",
|
||||
"integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-x64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz",
|
||||
"integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-arm64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz",
|
||||
"integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-x64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz",
|
||||
"integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz",
|
||||
"integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz",
|
||||
"integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ia32": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz",
|
||||
"integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-loong64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz",
|
||||
"integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-mips64el": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz",
|
||||
"integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==",
|
||||
"cpu": [
|
||||
"mips64el"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ppc64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz",
|
||||
"integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-riscv64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz",
|
||||
"integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-s390x": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz",
|
||||
"integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-x64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz",
|
||||
"integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-x64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz",
|
||||
"integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-x64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz",
|
||||
"integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/sunos-x64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz",
|
||||
"integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"sunos"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-arm64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz",
|
||||
"integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-ia32": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz",
|
||||
"integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-x64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz",
|
||||
"integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/cliui": {
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
|
||||
|
@ -207,6 +611,11 @@
|
|||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/lodash": {
|
||||
"version": "4.14.195",
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.195.tgz",
|
||||
"integrity": "sha512-Hwx9EUgdwf2GLarOjQp5ZH8ZmblzcbTBC2wtQWNKARBSxM9ezRIAUpeDTgoQRAFB0+8CNWXVA9+MaSOzOF3nPg=="
|
||||
},
|
||||
"node_modules/@types/mime": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz",
|
||||
|
@ -274,9 +683,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.8.2",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
|
||||
"integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
|
||||
"version": "8.9.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz",
|
||||
"integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
|
@ -350,6 +759,11 @@
|
|||
"safer-buffer": "~2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/asn1-ber": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/asn1-ber/-/asn1-ber-1.2.2.tgz",
|
||||
"integrity": "sha512-CbNem/7hxrjSiOAOOTX4iZxu+0m3jiLqlsERQwwPM1IDR/22M8IPpA1VVndCLw5KtjRYyRODbvAEIfuTogNDng=="
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
|
@ -401,6 +815,11 @@
|
|||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||
},
|
||||
"node_modules/boolean": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz",
|
||||
"integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw=="
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
|
@ -423,11 +842,37 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/bree": {
|
||||
"version": "9.1.3",
|
||||
"resolved": "https://registry.npmjs.org/bree/-/bree-9.1.3.tgz",
|
||||
"integrity": "sha512-oqto4iG7MG2xdRKU0MhFNPTq7ZSztKvalohO3nyu4EIyy3SKpLDX92LkptcGTl6BE2RpQLrzgBP3HoPtWlWBaA==",
|
||||
"dependencies": {
|
||||
"@breejs/later": "^4.1.0",
|
||||
"boolean": "^3.2.0",
|
||||
"combine-errors": "^3.0.3",
|
||||
"cron-validate": "^1.4.3",
|
||||
"human-interval": "^2.0.1",
|
||||
"is-string-and-not-blank": "^0.0.2",
|
||||
"is-valid-path": "^0.1.1",
|
||||
"ms": "^2.1.3",
|
||||
"p-wait-for": "3",
|
||||
"safe-timers": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.17.0 <13.0.0-0||>=13.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/buffer-equal-constant-time": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
|
||||
"integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="
|
||||
},
|
||||
"node_modules/buffer-from": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/bytes": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
||||
|
@ -493,6 +938,15 @@
|
|||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/combine-errors": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/combine-errors/-/combine-errors-3.0.3.tgz",
|
||||
"integrity": "sha512-C8ikRNRMygCwaTx+Ek3Yr+OuZzgZjduCOfSQBjbM8V3MfgcjSTeto/GXP6PAwKvJz/v15b7GHZvx5rOlczFw/Q==",
|
||||
"dependencies": {
|
||||
"custom-error-instance": "2.1.1",
|
||||
"lodash.uniqby": "4.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
|
@ -537,6 +991,14 @@
|
|||
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/cron-validate": {
|
||||
"version": "1.4.5",
|
||||
"resolved": "https://registry.npmjs.org/cron-validate/-/cron-validate-1.4.5.tgz",
|
||||
"integrity": "sha512-nKlOJEnYKudMn/aNyNH8xxWczlfpaazfWV32Pcx/2St51r2bxWbGhZD7uwzMcRhunA/ZNL+Htm/i0792Z59UMQ==",
|
||||
"dependencies": {
|
||||
"yup": "0.32.9"
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||
|
@ -551,6 +1013,11 @@
|
|||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/custom-error-instance": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/custom-error-instance/-/custom-error-instance-2.1.1.tgz",
|
||||
"integrity": "sha512-p6JFxJc3M4OTD2li2qaHkDCw9SfMw82Ldr6OC9Je1aXiGfhx2W8p3GaoeaGrPJTUN9NirTM/KTxHWMUdR1rsUg=="
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "3.2.7",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
|
||||
|
@ -630,6 +1097,43 @@
|
|||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.19.tgz",
|
||||
"integrity": "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"bin": {
|
||||
"esbuild": "bin/esbuild"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@esbuild/android-arm": "0.17.19",
|
||||
"@esbuild/android-arm64": "0.17.19",
|
||||
"@esbuild/android-x64": "0.17.19",
|
||||
"@esbuild/darwin-arm64": "0.17.19",
|
||||
"@esbuild/darwin-x64": "0.17.19",
|
||||
"@esbuild/freebsd-arm64": "0.17.19",
|
||||
"@esbuild/freebsd-x64": "0.17.19",
|
||||
"@esbuild/linux-arm": "0.17.19",
|
||||
"@esbuild/linux-arm64": "0.17.19",
|
||||
"@esbuild/linux-ia32": "0.17.19",
|
||||
"@esbuild/linux-loong64": "0.17.19",
|
||||
"@esbuild/linux-mips64el": "0.17.19",
|
||||
"@esbuild/linux-ppc64": "0.17.19",
|
||||
"@esbuild/linux-riscv64": "0.17.19",
|
||||
"@esbuild/linux-s390x": "0.17.19",
|
||||
"@esbuild/linux-x64": "0.17.19",
|
||||
"@esbuild/netbsd-x64": "0.17.19",
|
||||
"@esbuild/openbsd-x64": "0.17.19",
|
||||
"@esbuild/sunos-x64": "0.17.19",
|
||||
"@esbuild/win32-arm64": "0.17.19",
|
||||
"@esbuild/win32-ia32": "0.17.19",
|
||||
"@esbuild/win32-x64": "0.17.19"
|
||||
}
|
||||
},
|
||||
"node_modules/escape-html": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||
|
@ -841,6 +1345,18 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/get-tsconfig": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.6.0.tgz",
|
||||
"integrity": "sha512-lgbo68hHTQnFddybKbbs/RDRJnJT5YyGy2kQzVwbq+g67X73i+5MVTval34QxGkOe9X5Ujf1UYpCaphLyltjEg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"resolve-pkg-maps": "^1.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "10.2.7",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-10.2.7.tgz",
|
||||
|
@ -956,6 +1472,14 @@
|
|||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/human-interval": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/human-interval/-/human-interval-2.0.1.tgz",
|
||||
"integrity": "sha512-r4Aotzf+OtKIGQCB3odUowy4GfUDTy3aTWTfLd7ZF2gBCy3XW3v/dJLRefZnOFFnjqs5B1TypvS8WarpBkYUNQ==",
|
||||
"dependencies": {
|
||||
"numbered": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/iconv-lite": {
|
||||
"version": "0.4.24",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||
|
@ -1028,6 +1552,36 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-invalid-path": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-invalid-path/-/is-invalid-path-0.1.0.tgz",
|
||||
"integrity": "sha512-aZMG0T3F34mTg4eTdszcGXx54oiZ4NtHSft3hWNJMGJXUUqdIj3cOZuHcU0nCWWcY3jd7yRe/3AEm3vSNTpBGQ==",
|
||||
"dependencies": {
|
||||
"is-glob": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-invalid-path/node_modules/is-extglob": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
|
||||
"integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-invalid-path/node_modules/is-glob": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
|
||||
"integrity": "sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==",
|
||||
"dependencies": {
|
||||
"is-extglob": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
|
@ -1037,6 +1591,33 @@
|
|||
"node": ">=0.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-string-and-not-blank": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-string-and-not-blank/-/is-string-and-not-blank-0.0.2.tgz",
|
||||
"integrity": "sha512-FyPGAbNVyZpTeDCTXnzuwbu9/WpNXbCfbHXLpCRpN4GANhS00eEIP5Ef+k5HYSNIzIhdN9zRDoBj6unscECvtQ==",
|
||||
"dependencies": {
|
||||
"is-string-blank": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-string-blank": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-string-blank/-/is-string-blank-1.0.1.tgz",
|
||||
"integrity": "sha512-9H+ZBCVs3L9OYqv8nuUAzpcT9OTgMD1yAWrG7ihlnibdkbtB850heAmYWxHuXc4CHy4lKeK69tN+ny1K7gBIrw=="
|
||||
},
|
||||
"node_modules/is-valid-path": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-valid-path/-/is-valid-path-0.1.1.tgz",
|
||||
"integrity": "sha512-+kwPrVDu9Ms03L90Qaml+79+6DZHqHyRoANI6IsZJ/g8frhnfchDOBCa0RbQ6/kdHt5CS5OeIEyrYznNuVN+8A==",
|
||||
"dependencies": {
|
||||
"is-invalid-path": "^0.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/isexe": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
|
@ -1163,6 +1744,60 @@
|
|||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||
},
|
||||
"node_modules/lodash-es": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
|
||||
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
|
||||
},
|
||||
"node_modules/lodash._baseiteratee": {
|
||||
"version": "4.7.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash._baseiteratee/-/lodash._baseiteratee-4.7.0.tgz",
|
||||
"integrity": "sha512-nqB9M+wITz0BX/Q2xg6fQ8mLkyfF7MU7eE+MNBNjTHFKeKaZAPEzEg+E8LWxKWf1DQVflNEn9N49yAuqKh2mWQ==",
|
||||
"dependencies": {
|
||||
"lodash._stringtopath": "~4.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash._basetostring": {
|
||||
"version": "4.12.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-4.12.0.tgz",
|
||||
"integrity": "sha512-SwcRIbyxnN6CFEEK4K1y+zuApvWdpQdBHM/swxP962s8HIxPO3alBH5t3m/dl+f4CMUug6sJb7Pww8d13/9WSw=="
|
||||
},
|
||||
"node_modules/lodash._baseuniq": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz",
|
||||
"integrity": "sha512-Ja1YevpHZctlI5beLA7oc5KNDhGcPixFhcqSiORHNsp/1QTv7amAXzw+gu4YOvErqVlMVyIJGgtzeepCnnur0A==",
|
||||
"dependencies": {
|
||||
"lodash._createset": "~4.0.0",
|
||||
"lodash._root": "~3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash._createset": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/lodash._createset/-/lodash._createset-4.0.3.tgz",
|
||||
"integrity": "sha512-GTkC6YMprrJZCYU3zcqZj+jkXkrXzq3IPBcF/fIPpNEAB4hZEtXU8zp/RwKOvZl43NUmwDbyRk3+ZTbeRdEBXA=="
|
||||
},
|
||||
"node_modules/lodash._root": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz",
|
||||
"integrity": "sha512-O0pWuFSK6x4EXhM1dhZ8gchNtG7JMqBtrHdoUFUWXD7dJnNSUze1GuyQr5sOs0aCvgGeI3o/OJW8f4ca7FDxmQ=="
|
||||
},
|
||||
"node_modules/lodash._stringtopath": {
|
||||
"version": "4.8.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash._stringtopath/-/lodash._stringtopath-4.8.0.tgz",
|
||||
"integrity": "sha512-SXL66C731p0xPDC5LZg4wI5H+dJo/EO4KTqOMwLYCH3+FmmfAKJEZCm6ohGpI+T1xwsDsJCfL4OnhorllvlTPQ==",
|
||||
"dependencies": {
|
||||
"lodash._basetostring": "~4.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash.uniqby": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.5.0.tgz",
|
||||
"integrity": "sha512-IRt7cfTtHy6f1aRVA5n7kT8rgN3N1nH6MOWLcHfpWG2SH19E3JksLK38MktLxZDhlAjCP9jpIXkOnRXlu6oByQ==",
|
||||
"dependencies": {
|
||||
"lodash._baseiteratee": "~4.7.0",
|
||||
"lodash._baseuniq": "~4.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "9.1.2",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.2.tgz",
|
||||
|
@ -1255,6 +1890,11 @@
|
|||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
||||
},
|
||||
"node_modules/nanoclone": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz",
|
||||
"integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA=="
|
||||
},
|
||||
"node_modules/negotiator": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
|
||||
|
@ -1263,6 +1903,15 @@
|
|||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/net-snmp": {
|
||||
"version": "3.9.6",
|
||||
"resolved": "https://registry.npmjs.org/net-snmp/-/net-snmp-3.9.6.tgz",
|
||||
"integrity": "sha512-57MeEWjzp+1SEwRtE/uHowi9K5g5rxCQ0rX1Kc0ZtfjAauhx2mdk7hcE6Rdtw86eEoisuuPY3X79xxSRKbvQiA==",
|
||||
"dependencies": {
|
||||
"asn1-ber": "^1.2.1",
|
||||
"smart-buffer": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/nodemon": {
|
||||
"version": "2.0.22",
|
||||
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.22.tgz",
|
||||
|
@ -1315,6 +1964,11 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/numbered": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/numbered/-/numbered-1.1.0.tgz",
|
||||
"integrity": "sha512-pv/ue2Odr7IfYOO0byC1KgBI10wo5YDauLhxY6/saNzAdAs0r1SotGCPzzCLNPL0xtrAwWRialLu23AAu9xO1g=="
|
||||
},
|
||||
"node_modules/object-inspect": {
|
||||
"version": "1.12.3",
|
||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
|
||||
|
@ -1334,6 +1988,39 @@
|
|||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/p-finally": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
|
||||
"integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/p-timeout": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz",
|
||||
"integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==",
|
||||
"dependencies": {
|
||||
"p-finally": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/p-wait-for": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-wait-for/-/p-wait-for-3.2.0.tgz",
|
||||
"integrity": "sha512-wpgERjNkLrBiFmkMEjuZJEWKKDrNfHCKA1OhyN1wg1FrLkULbviEy6py1AyJUgZ72YWFbZ38FIpnqvVqAlDUwA==",
|
||||
"dependencies": {
|
||||
"p-timeout": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/parseurl": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
|
||||
|
@ -1401,6 +2088,11 @@
|
|||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/property-expr": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.5.tgz",
|
||||
"integrity": "sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA=="
|
||||
},
|
||||
"node_modules/proxy-addr": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
||||
|
@ -1467,6 +2159,20 @@
|
|||
"node": ">=8.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/regenerator-runtime": {
|
||||
"version": "0.13.11",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
|
||||
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
|
||||
},
|
||||
"node_modules/resolve-pkg-maps": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
|
||||
"integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
|
||||
"dev": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/rimraf": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.1.tgz",
|
||||
|
@ -1504,6 +2210,11 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"node_modules/safe-timers": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/safe-timers/-/safe-timers-1.1.0.tgz",
|
||||
"integrity": "sha512-9aqY+v5eMvmRaluUEtdRThV1EjlSElzO7HuCj0sTW9xvp++8iJ9t/RWGNWV6/WHcUJLHpyT2SNf/apoKTU2EpA=="
|
||||
},
|
||||
"node_modules/safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
|
@ -1640,6 +2351,34 @@
|
|||
"semver": "bin/semver.js"
|
||||
}
|
||||
},
|
||||
"node_modules/smart-buffer": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
|
||||
"integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
|
||||
"engines": {
|
||||
"node": ">= 6.0.0",
|
||||
"npm": ">= 3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-support": {
|
||||
"version": "0.5.21",
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
|
||||
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"buffer-from": "^1.0.0",
|
||||
"source-map": "^0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/statuses": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
|
||||
|
@ -1781,6 +2520,11 @@
|
|||
"node": ">=0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/toposort": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
|
||||
"integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg=="
|
||||
},
|
||||
"node_modules/touch": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
|
||||
|
@ -1836,6 +2580,23 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/tsx": {
|
||||
"version": "3.12.7",
|
||||
"resolved": "https://registry.npmjs.org/tsx/-/tsx-3.12.7.tgz",
|
||||
"integrity": "sha512-C2Ip+jPmqKd1GWVQDvz/Eyc6QJbGfE7NrR3fx5BpEHMZsEHoIxHL1j+lKdGobr8ovEyqeNkPLSKp6SCSOt7gmw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@esbuild-kit/cjs-loader": "^2.4.2",
|
||||
"@esbuild-kit/core-utils": "^3.0.0",
|
||||
"@esbuild-kit/esm-loader": "^2.5.5"
|
||||
},
|
||||
"bin": {
|
||||
"tsx": "dist/cli.js"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/type-is": {
|
||||
"version": "1.6.18",
|
||||
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
|
||||
|
@ -2024,6 +2785,23 @@
|
|||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/yup": {
|
||||
"version": "0.32.9",
|
||||
"resolved": "https://registry.npmjs.org/yup/-/yup-0.32.9.tgz",
|
||||
"integrity": "sha512-Ci1qN+i2H0XpY7syDQ0k5zKQ/DoxO0LzPg8PAR/X4Mpj6DqaeCoIYEEjDJwhArh3Fa7GWbQQVDZKeXYlSH4JMg==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.10.5",
|
||||
"@types/lodash": "^4.14.165",
|
||||
"lodash": "^4.17.20",
|
||||
"lodash-es": "^4.17.15",
|
||||
"nanoclone": "^0.2.1",
|
||||
"property-expr": "^2.0.4",
|
||||
"toposort": "^2.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
20
package.json
20
package.json
|
@ -1,17 +1,20 @@
|
|||
{
|
||||
"name": "ifms-healthtracker",
|
||||
"name": "ifms-printer-manager",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"clean": "rimraf ./dist",
|
||||
"build": "npm run clean && tsc",
|
||||
"start": "node dist",
|
||||
"dev": "nodemon --ext js,ts,mts,mjs,json,prisma ./src/index.ts --exec ts-node-esm"
|
||||
"clean": "rimraf ./dist ./public",
|
||||
"build:server": "npm run clean && tsc",
|
||||
"build:web": "cd web && npm run build",
|
||||
"build": "npm run build:server && npm run build:web",
|
||||
"start": "NODE_ENV=production node dist",
|
||||
"dev": "nodemon --ext js,ts,mts,mjs,json,prisma --exec \"tsx src/index.ts\"",
|
||||
"devLegacy": "NODE_OPTIONS=\"--loader ts-node/esm\" node ./src/index.ts"
|
||||
},
|
||||
"prisma": {
|
||||
"seed": "ts-node --esm prisma/seed.ts"
|
||||
"seed": "tsx prisma/seed.ts"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "Douglas Barone",
|
||||
|
@ -24,14 +27,17 @@
|
|||
"prisma": "^4.15.0",
|
||||
"rimraf": "^5.0.1",
|
||||
"ts-node": "^10.9.1",
|
||||
"tsx": "^3.12.7",
|
||||
"typescript": "^5.1.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "^4.15.0",
|
||||
"body-parser": "^1.20.2",
|
||||
"bree": "^9.1.3",
|
||||
"dotenv": "^16.1.4",
|
||||
"express": "^4.18.2",
|
||||
"jsonwebtoken": "^9.0.0",
|
||||
"ldapts": "^4.2.6"
|
||||
"ldapts": "^4.2.6",
|
||||
"net-snmp": "^3.9.6"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
-- CreateEnum
|
||||
CREATE TYPE "Role" AS ENUM ('ADMIN', 'INSPECTOR', 'USER');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "PrinterModel" AS ENUM ('m3655idn', 'm2040dn', 'p6235cdn');
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "User" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"username" TEXT,
|
||||
"mail" TEXT,
|
||||
"displayName" TEXT,
|
||||
"thumbnailPhoto" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"roles" "Role"[] DEFAULT ARRAY['USER']::"Role"[],
|
||||
|
||||
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Printer" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"hostname" TEXT,
|
||||
"friendlyName" TEXT,
|
||||
"ip" TEXT NOT NULL,
|
||||
"model" "PrinterModel" NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "Printer_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "User_username_key" ON "User"("username");
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
Warnings:
|
||||
|
||||
- A unique constraint covering the columns `[serialNumber]` on the table `Printer` will be added. If there are existing duplicate values, this will fail.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "Printer" ADD COLUMN "serialNumber" TEXT;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "PrinterStatus" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"tonerBlackLevel" INTEGER NOT NULL,
|
||||
"tonerCyanLevel" INTEGER,
|
||||
"tonerMagentaLevel" INTEGER,
|
||||
"tonerYellowLevel" INTEGER,
|
||||
"counter" INTEGER NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"printerId" INTEGER NOT NULL,
|
||||
|
||||
CONSTRAINT "PrinterStatus_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Printer_serialNumber_key" ON "Printer"("serialNumber");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "PrinterStatus" ADD CONSTRAINT "PrinterStatus_printerId_fkey" FOREIGN KEY ("printerId") REFERENCES "Printer"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
61
prisma/migrations/20230620175043_init/migration.sql
Normal file
61
prisma/migrations/20230620175043_init/migration.sql
Normal file
|
@ -0,0 +1,61 @@
|
|||
-- CreateEnum
|
||||
CREATE TYPE "Role" AS ENUM ('ADMIN', 'INSPECTOR', 'USER');
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "User" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"username" TEXT,
|
||||
"mail" TEXT,
|
||||
"displayName" TEXT,
|
||||
"thumbnailPhoto" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"roles" "Role"[] DEFAULT ARRAY['USER']::"Role"[],
|
||||
|
||||
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Printer" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"friendlyName" TEXT,
|
||||
"location" TEXT,
|
||||
"serialNumber" TEXT,
|
||||
"hostname" TEXT,
|
||||
"ip" TEXT NOT NULL,
|
||||
"model" TEXT NOT NULL,
|
||||
"blackTonerModel" TEXT,
|
||||
"cyanTonerModel" TEXT,
|
||||
"magentaTonerModel" TEXT,
|
||||
"yellowTonerModel" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "Printer_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "PrinterStatus" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"tonerBlackLevel" INTEGER NOT NULL,
|
||||
"tonerCyanLevel" INTEGER,
|
||||
"tonerMagentaLevel" INTEGER,
|
||||
"tonerYellowLevel" INTEGER,
|
||||
"counter" INTEGER NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"printerId" INTEGER NOT NULL,
|
||||
|
||||
CONSTRAINT "PrinterStatus_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "User_username_key" ON "User"("username");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Printer_serialNumber_key" ON "Printer"("serialNumber");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Printer_ip_key" ON "Printer"("ip");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "PrinterStatus" ADD CONSTRAINT "PrinterStatus_printerId_fkey" FOREIGN KEY ("printerId") REFERENCES "Printer"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
5
prisma/migrations/20230620191614_cascade/migration.sql
Normal file
5
prisma/migrations/20230620191614_cascade/migration.sql
Normal file
|
@ -0,0 +1,5 @@
|
|||
-- DropForeignKey
|
||||
ALTER TABLE "PrinterStatus" DROP CONSTRAINT "PrinterStatus_printerId_fkey";
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "PrinterStatus" ADD CONSTRAINT "PrinterStatus_printerId_fkey" FOREIGN KEY ("printerId") REFERENCES "Printer"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
@ -34,11 +34,12 @@ model Printer {
|
|||
id Int @id @default(autoincrement())
|
||||
|
||||
friendlyName String?
|
||||
location String?
|
||||
|
||||
serialNumber String? @unique
|
||||
hostname String?
|
||||
ip String
|
||||
model PrinterModel
|
||||
ip String @unique
|
||||
model String
|
||||
|
||||
blackTonerModel String?
|
||||
cyanTonerModel String?
|
||||
|
@ -48,13 +49,7 @@ model Printer {
|
|||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
|
||||
PrinterStatus PrinterStatus[]
|
||||
}
|
||||
|
||||
enum PrinterModel {
|
||||
m3655idn
|
||||
m2040dn
|
||||
p6235cdn
|
||||
status PrinterStatus[]
|
||||
}
|
||||
|
||||
model PrinterStatus {
|
||||
|
@ -70,5 +65,5 @@ model PrinterStatus {
|
|||
createdAt DateTime @default(now())
|
||||
|
||||
printerId Int
|
||||
printer Printer @relation(fields: [printerId], references: [id])
|
||||
printer Printer @relation(fields: [printerId], references: [id], onDelete: Cascade)
|
||||
}
|
||||
|
|
|
@ -6,33 +6,33 @@ async function main() {
|
|||
await prisma.printer.createMany({
|
||||
data: [
|
||||
{
|
||||
friendlyName: 'p04',
|
||||
friendlyName: 'P04',
|
||||
ip: '10.7.0.134',
|
||||
model: 'm3655idn',
|
||||
model: 'ECOSYS M3655idn',
|
||||
serialNumber: 'R4P1478461'
|
||||
},
|
||||
{
|
||||
friendlyName: 'p05',
|
||||
friendlyName: 'P05',
|
||||
ip: '10.7.0.135',
|
||||
model: 'm2040dn',
|
||||
model: 'ECOSYS M2040dn',
|
||||
serialNumber: 'VR91483974'
|
||||
},
|
||||
{
|
||||
friendlyName: 'p06',
|
||||
friendlyName: 'P06',
|
||||
ip: '10.7.0.136',
|
||||
model: 'm2040dn',
|
||||
model: 'ECOSYS M2040dn',
|
||||
serialNumber: 'VR91586433'
|
||||
},
|
||||
{
|
||||
friendlyName: 'p07',
|
||||
friendlyName: 'P07',
|
||||
ip: '10.7.0.137',
|
||||
model: 'm2040dn',
|
||||
model: 'ECOSYS M2040dn',
|
||||
serialNumber: 'VR91586432'
|
||||
},
|
||||
{
|
||||
friendlyName: 'p08',
|
||||
friendlyName: 'P08',
|
||||
ip: '10.7.0.138',
|
||||
model: 'p6235cdn',
|
||||
model: 'ECOSYS P6235cdn',
|
||||
serialNumber: 'RCG0304510'
|
||||
}
|
||||
]
|
||||
|
|
26
src/controllers/LoginController.ts
Normal file
26
src/controllers/LoginController.ts
Normal file
|
@ -0,0 +1,26 @@
|
|||
import { Request, Response, Router } from 'express'
|
||||
import { AuthenticationService } from '../services/AuthenticationService.js'
|
||||
|
||||
const router = Router()
|
||||
|
||||
class LoginController {
|
||||
static async login(req: Request, res: Response) {
|
||||
const { username, password } = req.body
|
||||
|
||||
if (!username || !password) {
|
||||
res.status(400).json({ error: 'Missing username or password' })
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const token = await AuthenticationService.login(username, password)
|
||||
res.json({ token })
|
||||
} catch (error: any) {
|
||||
res.status(401).json({ error: error.message })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
router.post('/', LoginController.login)
|
||||
|
||||
export default router
|
106
src/controllers/PrinterController.ts
Normal file
106
src/controllers/PrinterController.ts
Normal file
|
@ -0,0 +1,106 @@
|
|||
import { Request, Response, Router } from 'express'
|
||||
|
||||
import { hasRolesMiddleware } from '../middlewares/hasRolesMiddleware.js'
|
||||
import { prisma } from '../prisma.js'
|
||||
import { PrinterStatusService } from '../services/PrinterStatusService.js'
|
||||
import { distributedCopy } from '../utils/distributedCopy.js'
|
||||
|
||||
const router = Router()
|
||||
|
||||
class PrinterController {
|
||||
static async index(req: Request, res: Response) {
|
||||
const printers = await prisma.printer.findMany()
|
||||
|
||||
res.json(printers)
|
||||
}
|
||||
|
||||
static async show(req: Request, res: Response) {
|
||||
const { id } = req.params
|
||||
const { take, minutes = 43200 } = req.query
|
||||
|
||||
const gte = new Date(Date.now() - 1000 * 60 * Number(minutes))
|
||||
|
||||
const printer = await prisma.printer.findUnique({
|
||||
where: { id: Number(id) },
|
||||
include: {
|
||||
status: {
|
||||
where: {
|
||||
createdAt: {
|
||||
gte
|
||||
}
|
||||
},
|
||||
|
||||
orderBy: {
|
||||
createdAt: 'desc'
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (printer)
|
||||
res.json({
|
||||
...printer,
|
||||
status: distributedCopy(printer.status, Number(take))
|
||||
})
|
||||
else res.status(400).json({ error: 'Printer not found' })
|
||||
}
|
||||
|
||||
static async create(req: Request, res: Response) {
|
||||
const { friendlyName, ip } = req.body
|
||||
|
||||
try {
|
||||
const model = await PrinterStatusService.getPrinterModel(ip)
|
||||
const printer = await prisma.printer.create({
|
||||
data: { friendlyName, ip, model }
|
||||
})
|
||||
|
||||
new PrinterStatusService(printer)
|
||||
|
||||
res.json(printer)
|
||||
} catch (e) {
|
||||
res
|
||||
.status(400)
|
||||
.json({ error: 'Este endereço não é de uma impressora suportada.' })
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
static async edit(req: Request, res: Response) {
|
||||
const { id } = req.params
|
||||
const { friendlyName } = req.body
|
||||
|
||||
// Verify if printer exists
|
||||
const printerExists = await prisma.printer.findUnique({
|
||||
where: { id: Number(id) }
|
||||
})
|
||||
|
||||
if (printerExists) {
|
||||
const printer = await prisma.printer.update({
|
||||
where: { id: Number(id) },
|
||||
data: { friendlyName }
|
||||
})
|
||||
|
||||
res.json(printer)
|
||||
} else {
|
||||
res.status(400).json({ error: 'Printer not found' })
|
||||
}
|
||||
}
|
||||
|
||||
static async delete(req: Request, res: Response) {
|
||||
const { id } = req.params
|
||||
|
||||
await prisma.printer.delete({ where: { id: Number(id) } })
|
||||
|
||||
res.json({ message: 'Printer deleted' })
|
||||
}
|
||||
}
|
||||
|
||||
router.use(hasRolesMiddleware(['ADMIN', 'INSPECTOR']))
|
||||
|
||||
router.get('/', PrinterController.index)
|
||||
router.post('/', PrinterController.create)
|
||||
router.get('/:id', PrinterController.show)
|
||||
router.put('/:id', PrinterController.edit)
|
||||
router.delete('/:id', PrinterController.delete)
|
||||
|
||||
export default router
|
24
src/controllers/PrinterStatusController.ts
Normal file
24
src/controllers/PrinterStatusController.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
import { Router, Request, Response } from 'express'
|
||||
import { prisma } from '../prisma.js'
|
||||
import { PrinterStatusService } from '../services/PrinterStatusService.js'
|
||||
import { hasRolesMiddleware } from '../middlewares/hasRolesMiddleware.js'
|
||||
|
||||
const router = Router()
|
||||
|
||||
class PrinterStatusController {
|
||||
static async update(req: Request, res: Response) {
|
||||
const printers = await prisma.printer.findMany()
|
||||
|
||||
printers.forEach(async printer => {
|
||||
new PrinterStatusService(printer)
|
||||
})
|
||||
|
||||
res.json({ message: 'Updating printer status' })
|
||||
}
|
||||
}
|
||||
|
||||
router.use(hasRolesMiddleware(['ADMIN', 'INSPECTOR']))
|
||||
|
||||
router.post('/update', PrinterStatusController.update)
|
||||
|
||||
export default router
|
|
@ -1,18 +0,0 @@
|
|||
import { LdapController } from '../controllers/LdapController.js'
|
||||
import { prisma } from '../prisma.js'
|
||||
|
||||
export class UserController {
|
||||
static async importUser(username: string) {
|
||||
const ldap = new LdapController()
|
||||
|
||||
const user = await ldap.getUser(username)
|
||||
|
||||
if (!user) throw new Error('User not found!')
|
||||
|
||||
return await prisma.user.upsert({
|
||||
where: { username: user.username },
|
||||
update: user,
|
||||
create: user
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
import { UserController } from '../UserController.js'
|
||||
import { prisma } from '../../prisma.js'
|
||||
import { Request, Response } from 'express'
|
||||
|
||||
export class UserRouteController {
|
||||
static async getOne(req: Request, res: Response) {
|
||||
const { username } = req.params
|
||||
|
||||
if (!username) return res.status(400).json({ error: 'Missing username' })
|
||||
|
||||
try {
|
||||
const user = await prisma.user.findUnique({
|
||||
where: { username }
|
||||
})
|
||||
|
||||
if (!user) return await UserController.importUser(username)
|
||||
else UserController.importUser(username)
|
||||
|
||||
res.json(user)
|
||||
} catch (error: any) {
|
||||
res.status(500).json({ error: error.message })
|
||||
}
|
||||
}
|
||||
}
|
26
src/index.ts
26
src/index.ts
|
@ -1,9 +1,33 @@
|
|||
import 'dotenv/config'
|
||||
import * as path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
import { app } from './server.js'
|
||||
import Bree from 'bree'
|
||||
|
||||
const PORT = process.env.PORT || 3000
|
||||
|
||||
// Start server
|
||||
app.listen(PORT, () => {
|
||||
console.log(`Server listening on port ${PORT}`)
|
||||
console.log(
|
||||
`Running in ${
|
||||
process.env.NODE_ENV == 'production' ? 'PRODUCTION' : 'DEVELOPMENT'
|
||||
} mode. \nServer listening http://127.0.0.1:${PORT}`
|
||||
)
|
||||
})
|
||||
|
||||
// Jobs
|
||||
const bree = new Bree({
|
||||
root: path.join(path.dirname(fileURLToPath(import.meta.url)), 'jobs'),
|
||||
defaultExtension: process.env.NODE_ENV == 'production' ? 'js' : 'ts',
|
||||
logger: false,
|
||||
jobs: [
|
||||
{
|
||||
name: 'updatePrinterStatus',
|
||||
interval: process.env.UPDATE_INTERVAL || '10m',
|
||||
timeout: 0
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
bree.start()
|
||||
|
|
14
src/jobs/updatePrinterStatus.ts
Normal file
14
src/jobs/updatePrinterStatus.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { prisma } from '../prisma.js'
|
||||
import { PrinterStatusService } from '../services/PrinterStatusService.js'
|
||||
|
||||
function updatePrinterStatus() {
|
||||
console.log(`Updating printer status ${new Date().toISOString()}`)
|
||||
|
||||
prisma.printer.findMany().then(printers => {
|
||||
printers.forEach(async printer => {
|
||||
new PrinterStatusService(printer)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
updatePrinterStatus()
|
|
@ -1,13 +1,12 @@
|
|||
import { Response, NextFunction } from 'express'
|
||||
import { RequestWithUser } from '../types/RequestWithUser.js'
|
||||
import { Response, NextFunction, Request } from 'express'
|
||||
|
||||
export async function authMiddleware(
|
||||
req: RequestWithUser,
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
) {
|
||||
try {
|
||||
if (!req.user) {
|
||||
if (!res.locals.user) {
|
||||
res.status(401).json({ error: 'Must be logged in' })
|
||||
return
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
import { Response, NextFunction } from 'express'
|
||||
import { RequestWithUser } from '../types/RequestWithUser.js'
|
||||
import { Response, NextFunction, Request } from 'express'
|
||||
|
||||
import { Role } from '@prisma/client'
|
||||
|
||||
export function hasRolesMiddleware(roles: Role[]) {
|
||||
return function (req: RequestWithUser, res: Response, next: NextFunction) {
|
||||
return function (req: Request, res: Response, next: NextFunction) {
|
||||
try {
|
||||
const userRoles = req.user?.roles
|
||||
const userRoles = res.locals.user?.roles
|
||||
|
||||
if (roles.some(role => userRoles?.includes(role))) next()
|
||||
else res.status(401).json({ error: 'Not authorized!' })
|
|
@ -1,6 +1,5 @@
|
|||
import { NextFunction, Request, Response } from 'express'
|
||||
import { RequestWithUser } from '../types/RequestWithUser.js'
|
||||
import { AuthenticationController } from '../controllers/AuthenticationController.js'
|
||||
import { AuthenticationService } from '../services/AuthenticationService.js'
|
||||
|
||||
function getToken(req: Request) {
|
||||
const authHeader = req.headers.authorization as string
|
||||
|
@ -13,16 +12,20 @@ function getToken(req: Request) {
|
|||
return token
|
||||
}
|
||||
|
||||
export async function injectUserMiddleware(
|
||||
req: RequestWithUser,
|
||||
export async function populateUserMiddleware(
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
) {
|
||||
const token = getToken(req)
|
||||
|
||||
if (token) {
|
||||
const user = await AuthenticationController.authenticate(token)
|
||||
req.user = user
|
||||
try {
|
||||
const user = await AuthenticationService.jwtAuth(token)
|
||||
res.locals.user = user
|
||||
} catch (error: any) {
|
||||
return res.status(401).json({ error: error.message })
|
||||
}
|
||||
}
|
||||
|
||||
next()
|
109
src/repositories/ObjectIDRepository.ts
Normal file
109
src/repositories/ObjectIDRepository.ts
Normal file
|
@ -0,0 +1,109 @@
|
|||
export type PrinterObjectIds = {
|
||||
model: string
|
||||
objectIds: {
|
||||
model: string
|
||||
serialNumber: string
|
||||
counter: string
|
||||
location: string
|
||||
toners: {
|
||||
black: {
|
||||
current: string
|
||||
max: string
|
||||
model: string
|
||||
}
|
||||
cyan?: {
|
||||
current: string
|
||||
max: string
|
||||
model: string
|
||||
}
|
||||
magenta?: {
|
||||
current: string
|
||||
max: string
|
||||
model: string
|
||||
}
|
||||
yellow?: {
|
||||
current: string
|
||||
max: string
|
||||
model: string
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const objectIds: PrinterObjectIds[] = [
|
||||
{
|
||||
model: 'ECOSYS M3655idn',
|
||||
objectIds: {
|
||||
model: '1.3.6.1.2.1.25.3.2.1.3.1',
|
||||
serialNumber: '1.3.6.1.2.1.43.5.1.1.17.1',
|
||||
counter: '1.3.6.1.4.1.1347.43.10.1.1.12.1.1',
|
||||
location: '1.3.6.1.2.1.1.6.0',
|
||||
toners: {
|
||||
black: {
|
||||
current: '1.3.6.1.2.1.43.11.1.1.9.1.1',
|
||||
max: '1.3.6.1.2.1.43.11.1.1.8.1.1',
|
||||
model: '1.3.6.1.2.1.43.11.1.1.6.1.1'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
model: 'ECOSYS P6235cdn',
|
||||
objectIds: {
|
||||
model: '1.3.6.1.2.1.25.3.2.1.3.1',
|
||||
serialNumber: '1.3.6.1.2.1.43.5.1.1.17.1',
|
||||
counter: '1.3.6.1.4.1.1347.43.10.1.1.12.1.1',
|
||||
location: '1.3.6.1.2.1.1.6.0',
|
||||
toners: {
|
||||
black: {
|
||||
current: '1.3.6.1.2.1.43.11.1.1.9.1.4',
|
||||
max: '1.3.6.1.2.1.43.11.1.1.8.1.4',
|
||||
model: '1.3.6.1.2.1.43.11.1.1.6.1.4'
|
||||
},
|
||||
cyan: {
|
||||
current: '1.3.6.1.2.1.43.11.1.1.9.1.1',
|
||||
max: '1.3.6.1.2.1.43.11.1.1.8.1.1',
|
||||
model: '1.3.6.1.2.1.43.11.1.1.6.1.1'
|
||||
},
|
||||
magenta: {
|
||||
current: '1.3.6.1.2.1.43.11.1.1.9.1.2',
|
||||
max: '1.3.6.1.2.1.43.11.1.1.8.1.2',
|
||||
model: '1.3.6.1.2.1.43.11.1.1.6.1.2'
|
||||
},
|
||||
yellow: {
|
||||
current: '1.3.6.1.2.1.43.11.1.1.9.1.3',
|
||||
max: '1.3.6.1.2.1.43.11.1.1.8.1.3',
|
||||
model: '1.3.6.1.2.1.43.11.1.1.6.1.3'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
model: 'ECOSYS M2040dn',
|
||||
objectIds: {
|
||||
model: '1.3.6.1.2.1.25.3.2.1.3.1',
|
||||
serialNumber: '1.3.6.1.2.1.43.5.1.1.17.1',
|
||||
counter: '1.3.6.1.4.1.1347.43.10.1.1.12.1.1',
|
||||
location: '1.3.6.1.2.1.1.6.0',
|
||||
toners: {
|
||||
black: {
|
||||
current: '1.3.6.1.2.1.43.11.1.1.9.1.1',
|
||||
max: '1.3.6.1.2.1.43.11.1.1.8.1.1',
|
||||
model: '1.3.6.1.2.1.43.11.1.1.6.1.1'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
export class objectIdsRepository {
|
||||
private constructor() {}
|
||||
|
||||
static getPrinterObjectIds(model: string): PrinterObjectIds {
|
||||
const printerObjectIds = objectIds.find(printer => printer.model === model)
|
||||
|
||||
if (!printerObjectIds) throw new Error('Model not found')
|
||||
|
||||
return printerObjectIds
|
||||
}
|
||||
}
|
|
@ -1,67 +1,24 @@
|
|||
import express, { Request, Response } from 'express'
|
||||
import bodyParser from 'body-parser'
|
||||
|
||||
import { injectUserMiddleware } from './middleware/injectUserMiddleware.js'
|
||||
import { authMiddleware } from './middleware/authMiddleware.js'
|
||||
import { hasRolesMiddleware } from './middleware/hasRolesMiddleware.js'
|
||||
import { populateUserMiddleware } from './middlewares/populateUserMiddleware.js'
|
||||
import { authMiddleware } from './middlewares/authMiddleware.js'
|
||||
|
||||
import { RequestWithUser } from './types/RequestWithUser.js'
|
||||
|
||||
import { UserRouteController } from './controllers/routes/UserRouteController.js'
|
||||
import { AuthenticationController } from './controllers/AuthenticationController.js'
|
||||
import LoginRouter from './controllers/LoginController.js'
|
||||
import PrinterRouter from './controllers/PrinterController.js'
|
||||
import PrinterStatusRouter from './controllers/PrinterStatusController.js'
|
||||
|
||||
export const app = express()
|
||||
|
||||
app.use('/', express.static('public'))
|
||||
|
||||
app.use(injectUserMiddleware)
|
||||
|
||||
app.use(bodyParser.json())
|
||||
app.use(populateUserMiddleware)
|
||||
|
||||
// Test route
|
||||
app.get('/api/', async (req: Request, res: Response) => {
|
||||
res.json({ message: 'Hello!' })
|
||||
})
|
||||
app.use('/api/login', LoginRouter)
|
||||
app.use('/api/printer', PrinterRouter)
|
||||
app.use('/api/printer-status', PrinterStatusRouter)
|
||||
|
||||
// Login route
|
||||
app.post('/api/login', async (req: Request, res: Response) => {
|
||||
const { username, password } = req.body
|
||||
|
||||
if (!username || !password)
|
||||
return res.status(400).json({ error: 'Missing username or password' })
|
||||
|
||||
try {
|
||||
const token = await AuthenticationController.login(username, password)
|
||||
res.json({ token })
|
||||
} catch (error: any) {
|
||||
res.status(401).json({ error: error.message })
|
||||
}
|
||||
})
|
||||
|
||||
app.get(
|
||||
'/api/me',
|
||||
authMiddleware,
|
||||
async (req: RequestWithUser, res: Response) => res.json(req.user)
|
||||
)
|
||||
|
||||
app.get(
|
||||
'/api/protected',
|
||||
authMiddleware,
|
||||
async (req: RequestWithUser, res: Response) => {
|
||||
res.json('Hello protected world! ' + req.user?.displayName)
|
||||
}
|
||||
)
|
||||
|
||||
app.get(
|
||||
'/api/admin',
|
||||
hasRolesMiddleware(['ADMIN']),
|
||||
async (req: RequestWithUser, res: Response) => {
|
||||
res.json('Hello Admin!' + req.user?.username)
|
||||
}
|
||||
)
|
||||
|
||||
app.get(
|
||||
'/api/user/:username',
|
||||
hasRolesMiddleware(['ADMIN']),
|
||||
UserRouteController.getOne
|
||||
app.get('/api/me', authMiddleware, async (req: Request, res: Response) =>
|
||||
res.json(res.locals.user)
|
||||
)
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
import jwt from 'jsonwebtoken'
|
||||
import { prisma } from '../prisma.js'
|
||||
import { LdapController } from '../controllers/LdapController.js'
|
||||
import { UserController } from '../controllers/UserController.js'
|
||||
import { LdapService } from './LdapService.js'
|
||||
import { UserService } from './UserService.js'
|
||||
|
||||
const JWT_SECRET = process.env.JWT_SECRET || 'secret'
|
||||
|
||||
export class AuthenticationController {
|
||||
export class AuthenticationService {
|
||||
private constructor() {}
|
||||
|
||||
static async login(username: string, password: string) {
|
||||
const ldap = new LdapController()
|
||||
const ldap = new LdapService()
|
||||
|
||||
await ldap.authenticate(username, password)
|
||||
|
||||
await UserController.importUser(username)
|
||||
await UserService.importUser(username)
|
||||
|
||||
const token = jwt.sign({ username }, JWT_SECRET, {
|
||||
expiresIn: '2 days'
|
||||
|
@ -22,7 +22,7 @@ export class AuthenticationController {
|
|||
return `Bearer ${token}`
|
||||
}
|
||||
|
||||
static async authenticate(token: string) {
|
||||
static async jwtAuth(token: string) {
|
||||
try {
|
||||
const { username } = jwt.verify(token, JWT_SECRET) as { username: string }
|
||||
|
||||
|
@ -30,11 +30,11 @@ export class AuthenticationController {
|
|||
where: { username }
|
||||
})
|
||||
|
||||
if (!user) return null
|
||||
if (!user) return await UserService.importUser(username)
|
||||
|
||||
return user
|
||||
} catch (error: any) {
|
||||
throw new Error('Invalid token')
|
||||
throw new Error(`Invalid token. ${error.message}`)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@ const BIND_USER = process.env.AD_BIND_USER || ''
|
|||
const BIND_PASSWD = process.env.AD_BIND_PASSWORD || ''
|
||||
|
||||
interface LdapClientInterface extends Client {
|
||||
authenticate(username: string, password: string): Promise<LdapUser | null>
|
||||
authenticate(username: string, password: string): Promise<void>
|
||||
getUser(username: string): Promise<any>
|
||||
}
|
||||
|
||||
|
@ -15,19 +15,20 @@ type LdapUser = {
|
|||
mail: string | null
|
||||
displayName: string
|
||||
thumbnailPhoto: string | null
|
||||
groups?: string[]
|
||||
}
|
||||
|
||||
export class LdapController extends Client implements LdapClientInterface {
|
||||
private static instance: LdapController
|
||||
export class LdapService extends Client implements LdapClientInterface {
|
||||
private static instance: LdapService
|
||||
|
||||
constructor() {
|
||||
if (LdapController.instance) return LdapController.instance
|
||||
if (LdapService.instance) return LdapService.instance
|
||||
|
||||
super({
|
||||
url: `ldap://${process.env.AD_HOST}`
|
||||
})
|
||||
|
||||
LdapController.instance = this
|
||||
LdapService.instance = this
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -45,19 +46,25 @@ export class LdapController extends Client implements LdapClientInterface {
|
|||
}
|
||||
}
|
||||
|
||||
async getUser(username: string) {
|
||||
async getUser(username: string): Promise<LdapUser> {
|
||||
return await this.adminBondOperation(async () => {
|
||||
const { searchEntries } = await this.search(DN, {
|
||||
scope: 'sub',
|
||||
filter: `(sAMAccountName=${username})`,
|
||||
attributes: ['mail', 'sAMAccountName', 'displayName', 'thumbnailPhoto'],
|
||||
attributes: [
|
||||
'mail',
|
||||
'sAMAccountName',
|
||||
'displayName',
|
||||
'thumbnailPhoto',
|
||||
'dn'
|
||||
],
|
||||
explicitBufferAttributes: ['thumbnailPhoto']
|
||||
})
|
||||
|
||||
if (!searchEntries.length)
|
||||
throw new Error('User not found on LDAP server.')
|
||||
|
||||
const { sAMAccountName, displayName, mail, thumbnailPhoto } =
|
||||
const { sAMAccountName, displayName, mail, thumbnailPhoto, dn } =
|
||||
searchEntries[0]
|
||||
|
||||
const ldapUser: LdapUser = {
|
||||
|
@ -66,20 +73,29 @@ export class LdapController extends Client implements LdapClientInterface {
|
|||
mail: mail.toString(),
|
||||
thumbnailPhoto: `data:image/png;base64,${Buffer.from(
|
||||
thumbnailPhoto as Buffer
|
||||
).toString('base64')}`
|
||||
).toString('base64')}`,
|
||||
groups: await this.getGroupsForUser(dn.toString())
|
||||
}
|
||||
|
||||
return ldapUser
|
||||
})
|
||||
}
|
||||
|
||||
async getGroupsForUser(dn: string) {
|
||||
const { searchEntries } = await this.search(DN, {
|
||||
scope: 'sub',
|
||||
filter: `(member:1.2.840.113556.1.4.1941:=${dn})`,
|
||||
attributes: ['cn']
|
||||
})
|
||||
|
||||
if (!searchEntries.length) throw new Error('User not found on LDAP server.')
|
||||
|
||||
return searchEntries.map(entry => entry.cn.toString())
|
||||
}
|
||||
|
||||
async authenticate(username: string, password: string) {
|
||||
await this.bind(`${DOMAIN}\\${username}`, password)
|
||||
|
||||
const user = await this.getUser(username)
|
||||
|
||||
await this.unbind()
|
||||
|
||||
return user
|
||||
}
|
||||
}
|
213
src/services/PrinterStatusService.ts
Normal file
213
src/services/PrinterStatusService.ts
Normal file
|
@ -0,0 +1,213 @@
|
|||
import snmp from 'net-snmp'
|
||||
import { Printer, PrinterStatus } from '@prisma/client'
|
||||
import { prisma } from '../prisma.js'
|
||||
import {
|
||||
objectIdsRepository,
|
||||
PrinterObjectIds
|
||||
} from '../repositories/ObjectIDRepository.js'
|
||||
|
||||
type VarbindString = {
|
||||
oid: string
|
||||
type: number
|
||||
value: string
|
||||
}
|
||||
|
||||
export type Varbind = {
|
||||
oid: string
|
||||
type: number
|
||||
value: string | Buffer
|
||||
}
|
||||
|
||||
export type PrinterInfo = {
|
||||
serialNumber: string
|
||||
counter: number
|
||||
location: string
|
||||
toners: {
|
||||
black: {
|
||||
level: number
|
||||
model: string
|
||||
}
|
||||
cyan?: {
|
||||
level: number
|
||||
model: string
|
||||
}
|
||||
magenta?: {
|
||||
level: number
|
||||
model: string
|
||||
}
|
||||
yellow?: {
|
||||
level: number
|
||||
model: string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class PrinterStatusService {
|
||||
constructor(private printer: Printer) {
|
||||
this.getPrinterInfo().then(async printerStatus => {
|
||||
await prisma.printer.update({
|
||||
where: { id: this.printer.id },
|
||||
data: {
|
||||
serialNumber: printerStatus.serialNumber,
|
||||
location: printerStatus.location,
|
||||
blackTonerModel: printerStatus.toners.black.model,
|
||||
cyanTonerModel: printerStatus.toners.cyan?.model,
|
||||
magentaTonerModel: printerStatus.toners.magenta?.model,
|
||||
yellowTonerModel: printerStatus.toners.yellow?.model,
|
||||
|
||||
status: {
|
||||
create: {
|
||||
counter: printerStatus.counter,
|
||||
tonerBlackLevel: printerStatus.toners.black.level,
|
||||
tonerCyanLevel: printerStatus.toners.cyan?.level,
|
||||
tonerMagentaLevel: printerStatus.toners.magenta?.level,
|
||||
tonerYellowLevel: printerStatus.toners.yellow?.level
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
private objectIdsArray(): string[] {
|
||||
const oIDsArray: string[] = []
|
||||
|
||||
function extractObjValues(obj: any) {
|
||||
for (let key in obj) {
|
||||
if (typeof obj[key] === 'object') {
|
||||
extractObjValues(obj[key])
|
||||
} else {
|
||||
const oID = obj[key]
|
||||
oIDsArray.push(oID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extractObjValues(
|
||||
objectIdsRepository.getPrinterObjectIds(this.printer.model).objectIds
|
||||
)
|
||||
|
||||
return oIDsArray
|
||||
}
|
||||
|
||||
private deBufferizeVarbinds(varbinds: Varbind[]) {
|
||||
const varbindsString: VarbindString[] = []
|
||||
|
||||
varbinds.forEach((varbind: Varbind) => {
|
||||
if (varbind.value instanceof Buffer)
|
||||
varbindsString.push({ ...varbind, value: varbind.value.toString() })
|
||||
else varbindsString.push({ ...varbind, value: varbind.value })
|
||||
})
|
||||
|
||||
return varbindsString
|
||||
}
|
||||
|
||||
static getPrinterModel(ip: string): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const snmpSession = snmp.createSession(ip, 'public')
|
||||
snmpSession.get(
|
||||
['1.3.6.1.2.1.25.3.2.1.3.1'],
|
||||
(error: any, varbinds: any) => {
|
||||
if (error) {
|
||||
reject(error)
|
||||
} else {
|
||||
resolve(varbinds[0].value.toString())
|
||||
}
|
||||
snmpSession.close()
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
async getPrinterInfo(): Promise<PrinterInfo> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const session = snmp.createSession(this.printer.ip, 'public')
|
||||
|
||||
const oIDsArray = this.objectIdsArray()
|
||||
|
||||
session.get(oIDsArray, (error: any, varbinds: Varbind[]) => {
|
||||
if (error) reject(error)
|
||||
|
||||
const varbindsString = this.deBufferizeVarbinds(varbinds)
|
||||
const info = this.objectIDsToPrinterInfo(varbindsString)
|
||||
|
||||
resolve(info)
|
||||
session.close()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
private calcTonerLevelPercentage(
|
||||
current: string | undefined,
|
||||
max: string | undefined
|
||||
) {
|
||||
if (typeof current === 'undefined' || typeof max === 'undefined')
|
||||
throw new Error('current or max is undefined')
|
||||
|
||||
return (+current! / +max!) * 100
|
||||
}
|
||||
|
||||
private objectIDsToPrinterInfo(varbinds: Varbind[]): PrinterInfo {
|
||||
const snmpInfo = this.deBufferizeVarbinds(varbinds)
|
||||
|
||||
const { objectIds }: PrinterObjectIds =
|
||||
objectIdsRepository.getPrinterObjectIds(this.printer.model)
|
||||
|
||||
const printerInfo: PrinterInfo = {
|
||||
serialNumber: snmpInfo.find(x => x.oid === objectIds.serialNumber)
|
||||
?.value as string,
|
||||
counter: Number(snmpInfo.find(x => x.oid === objectIds.counter)?.value),
|
||||
location: snmpInfo.find(x => x.oid === objectIds.location)
|
||||
?.value as string,
|
||||
toners: {
|
||||
black: {
|
||||
level: this.calcTonerLevelPercentage(
|
||||
snmpInfo.find(x => x.oid === objectIds.toners.black.current)?.value,
|
||||
snmpInfo.find(x => x.oid === objectIds.toners.black.max)?.value
|
||||
),
|
||||
model: snmpInfo.find(x => x.oid === objectIds.toners.black.model)
|
||||
?.value as string
|
||||
},
|
||||
cyan: objectIds.toners.cyan
|
||||
? {
|
||||
level: this.calcTonerLevelPercentage(
|
||||
snmpInfo.find(x => x.oid === objectIds.toners.cyan?.current)
|
||||
?.value,
|
||||
snmpInfo.find(x => x.oid === objectIds.toners.cyan?.max)?.value
|
||||
),
|
||||
model: snmpInfo.find(x => x.oid === objectIds.toners.cyan?.model)
|
||||
?.value as string
|
||||
}
|
||||
: undefined,
|
||||
magenta: objectIds.toners.magenta
|
||||
? {
|
||||
level: this.calcTonerLevelPercentage(
|
||||
snmpInfo.find(x => x.oid === objectIds.toners.magenta?.current)
|
||||
?.value,
|
||||
snmpInfo.find(x => x.oid === objectIds.toners.magenta?.max)
|
||||
?.value
|
||||
),
|
||||
model: snmpInfo.find(
|
||||
x => x.oid === objectIds.toners.magenta?.model
|
||||
)?.value as string
|
||||
}
|
||||
: undefined,
|
||||
yellow: objectIds.toners.yellow
|
||||
? {
|
||||
level: this.calcTonerLevelPercentage(
|
||||
snmpInfo.find(x => x.oid === objectIds.toners.yellow?.current)
|
||||
?.value,
|
||||
snmpInfo.find(x => x.oid === objectIds.toners.yellow?.max)
|
||||
?.value
|
||||
),
|
||||
model: snmpInfo.find(
|
||||
x => x.oid === objectIds.toners.yellow?.model
|
||||
)?.value as string
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
}
|
||||
|
||||
return printerInfo
|
||||
}
|
||||
}
|
37
src/services/UserService.ts
Normal file
37
src/services/UserService.ts
Normal file
|
@ -0,0 +1,37 @@
|
|||
import { User } from '@prisma/client'
|
||||
import { LdapService } from './LdapService.js'
|
||||
import { prisma } from '../prisma.js'
|
||||
|
||||
const ADMIN_GROUP = process.env.ADMIN_GROUP || 'PP-SERTI'
|
||||
const INSPECTOR_GROUP = process.env.INSPECTOR_GROUP || 'Inspectors'
|
||||
const USER_GROUP = process.env.USER_GROUP || 'G_SERVIDORES'
|
||||
|
||||
export class UserService {
|
||||
static async importUser(username: string) {
|
||||
const ldap = new LdapService()
|
||||
|
||||
const ldapUser = await ldap.getUser(username)
|
||||
|
||||
if (!ldapUser) throw new Error('User not found!')
|
||||
|
||||
const user: Omit<User, 'id' | 'createdAt' | 'updatedAt'> = {
|
||||
username: ldapUser.username,
|
||||
displayName: ldapUser.displayName,
|
||||
mail: ldapUser.mail,
|
||||
thumbnailPhoto: ldapUser.thumbnailPhoto,
|
||||
roles: []
|
||||
}
|
||||
|
||||
ldapUser.groups?.forEach(group => {
|
||||
if (group === USER_GROUP) user.roles?.push('USER')
|
||||
if (group === ADMIN_GROUP) user.roles?.push('ADMIN')
|
||||
if (group === INSPECTOR_GROUP) user.roles?.push('INSPECTOR')
|
||||
})
|
||||
|
||||
return await prisma.user.upsert({
|
||||
where: { username: ldapUser.username },
|
||||
update: user,
|
||||
create: user
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
import { Request } from 'express'
|
||||
import { User } from '@prisma/client'
|
||||
|
||||
export interface RequestWithUser extends Request {
|
||||
user?: User | null
|
||||
}
|
23
src/utils/distributedCopy.ts
Normal file
23
src/utils/distributedCopy.ts
Normal file
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* Retrieve a fixed number of elements from an array, evenly distributed but
|
||||
* always including the first and last elements.
|
||||
*
|
||||
* @param {Array} originalArray - The array to operate on.
|
||||
* @param {number} take - The number of elements to extract.
|
||||
* @returns {Array}
|
||||
*/
|
||||
|
||||
export function distributedCopy(originalArray: Array<any>, take: number = 10) {
|
||||
if (originalArray.length <= take) return [...originalArray]
|
||||
|
||||
const newArray = [originalArray[0]]
|
||||
|
||||
const interval = (originalArray.length - 2) / (take - 2)
|
||||
|
||||
for (let i = 1; i < take - 1; i++)
|
||||
newArray.push(originalArray[Math.floor(interval * i)])
|
||||
|
||||
newArray.push(originalArray[originalArray.length - 1])
|
||||
|
||||
return newArray
|
||||
}
|
|
@ -14,8 +14,8 @@
|
|||
"target": "ES2020" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
|
||||
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
||||
// "jsx": "preserve", /* Specify what JSX code is generated. */
|
||||
// "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
|
||||
"experimentalDecorators": true /* Enable experimental support for legacy experimental decorators. */,
|
||||
"emitDecoratorMetadata": true /* Emit design-type metadata for decorated declarations in source files. */,
|
||||
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
|
||||
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
|
||||
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
|
||||
|
@ -106,5 +106,5 @@
|
|||
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
|
||||
"skipLibCheck": true /* Skip type checking all .d.ts files. */
|
||||
},
|
||||
"include": ["src/**/*"]
|
||||
"include": ["src/**/*", "jobs/**/*", "globals.d.ts"]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user