User endpoints created
Invoices can now be fetched
This commit is contained in:
170
package-lock.json
generated
170
package-lock.json
generated
@@ -46,6 +46,11 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/component-emitter": {
|
||||||
|
"version": "1.2.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.10.tgz",
|
||||||
|
"integrity": "sha512-bsjleuRKWmGqajMerkzox19aGbscQX5rmmvvXl3wlIp5gMG1HgkiwPxsN5p070fBDKTNSPgojVbuY1+HWMbFhg=="
|
||||||
|
},
|
||||||
"@types/connect": {
|
"@types/connect": {
|
||||||
"version": "3.4.34",
|
"version": "3.4.34",
|
||||||
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.34.tgz",
|
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.34.tgz",
|
||||||
@@ -54,11 +59,15 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/cookie": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.0.tgz",
|
||||||
|
"integrity": "sha512-y7mImlc/rNkvCRmg8gC3/lj87S7pTUIJ6QGjwHR9WQJcFs+ZMTOaoPrkdFA/YdbuqVEmEbb5RdhVxMkAcgOnpg=="
|
||||||
|
},
|
||||||
"@types/cors": {
|
"@types/cors": {
|
||||||
"version": "2.8.9",
|
"version": "2.8.9",
|
||||||
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.9.tgz",
|
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.9.tgz",
|
||||||
"integrity": "sha512-zurD1ibz21BRlAOIKP8yhrxlqKx6L9VCwkB5kMiP6nZAhoF5MvC7qS1qPA7nRcr1GJolfkQC7/EAL4hdYejLtg==",
|
"integrity": "sha512-zurD1ibz21BRlAOIKP8yhrxlqKx6L9VCwkB5kMiP6nZAhoF5MvC7qS1qPA7nRcr1GJolfkQC7/EAL4hdYejLtg=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"@types/dotenv": {
|
"@types/dotenv": {
|
||||||
"version": "8.2.0",
|
"version": "8.2.0",
|
||||||
@@ -69,6 +78,15 @@
|
|||||||
"dotenv": "*"
|
"dotenv": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/engine.io": {
|
||||||
|
"version": "3.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/engine.io/-/engine.io-3.1.4.tgz",
|
||||||
|
"integrity": "sha512-98rXVukLD6/ozrQ2O80NAlWDGA4INg+tqsEReWJldqyi2fulC9V7Use/n28SWgROXKm6003ycWV4gZHoF8GA6w==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/express": {
|
"@types/express": {
|
||||||
"version": "4.17.9",
|
"version": "4.17.9",
|
||||||
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.9.tgz",
|
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.9.tgz",
|
||||||
@@ -164,6 +182,26 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/socket.io": {
|
||||||
|
"version": "2.1.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/socket.io/-/socket.io-2.1.12.tgz",
|
||||||
|
"integrity": "sha512-oStc5VFkpb0AsjOxQUj9ztX5Iziatyla/rjZTYbFGoVrrKwd+JU2mtxk7iSl5RGYx9WunLo6UXW1fBzQok/ZyA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/engine.io": "*",
|
||||||
|
"@types/node": "*",
|
||||||
|
"@types/socket.io-parser": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@types/socket.io-parser": {
|
||||||
|
"version": "2.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/socket.io-parser/-/socket.io-parser-2.2.1.tgz",
|
||||||
|
"integrity": "sha512-+JNb+7N7tSINyXPxAJb62+NcpC1x/fPn7z818W4xeNCdPTp6VsO/X8fCsg6+ug4a56m1v9sEiTIIUKVupcHOFQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/typescript": {
|
"@types/typescript": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/typescript/-/typescript-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/typescript/-/typescript-2.0.0.tgz",
|
||||||
@@ -283,6 +321,16 @@
|
|||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
|
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
|
||||||
},
|
},
|
||||||
|
"base64-arraybuffer": {
|
||||||
|
"version": "0.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz",
|
||||||
|
"integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI="
|
||||||
|
},
|
||||||
|
"base64id": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog=="
|
||||||
|
},
|
||||||
"bignumber.js": {
|
"bignumber.js": {
|
||||||
"version": "9.0.0",
|
"version": "9.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz",
|
||||||
@@ -439,6 +487,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
|
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
|
||||||
},
|
},
|
||||||
|
"component-emitter": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
|
||||||
|
},
|
||||||
"concat-map": {
|
"concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||||
@@ -562,6 +615,48 @@
|
|||||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||||
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
|
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
|
||||||
},
|
},
|
||||||
|
"engine.io": {
|
||||||
|
"version": "4.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-4.0.5.tgz",
|
||||||
|
"integrity": "sha512-Ri+whTNr2PKklxQkfbGjwEo+kCBUM4Qxk4wtLqLrhH+b1up2NFL9g9pjYWiCV/oazwB0rArnvF/ZmZN2ab5Hpg==",
|
||||||
|
"requires": {
|
||||||
|
"accepts": "~1.3.4",
|
||||||
|
"base64id": "2.0.0",
|
||||||
|
"cookie": "~0.4.1",
|
||||||
|
"cors": "~2.8.5",
|
||||||
|
"debug": "~4.1.0",
|
||||||
|
"engine.io-parser": "~4.0.0",
|
||||||
|
"ws": "^7.1.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"cookie": {
|
||||||
|
"version": "0.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
|
||||||
|
"integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA=="
|
||||||
|
},
|
||||||
|
"debug": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
|
||||||
|
"requires": {
|
||||||
|
"ms": "^2.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ms": {
|
||||||
|
"version": "2.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"engine.io-parser": {
|
||||||
|
"version": "4.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-4.0.2.tgz",
|
||||||
|
"integrity": "sha512-sHfEQv6nmtJrq6TKuIz5kyEKH/qSdK56H/A+7DnAuUPWosnIZAS2NHNcPLmyjtY3cGS/MqJdZbUjW97JU72iYg==",
|
||||||
|
"requires": {
|
||||||
|
"base64-arraybuffer": "0.1.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"es6-promise": {
|
"es6-promise": {
|
||||||
"version": "4.2.8",
|
"version": "4.2.8",
|
||||||
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
|
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
|
||||||
@@ -1508,6 +1603,72 @@
|
|||||||
"resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz",
|
||||||
"integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E="
|
"integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E="
|
||||||
},
|
},
|
||||||
|
"socket.io": {
|
||||||
|
"version": "3.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-3.0.4.tgz",
|
||||||
|
"integrity": "sha512-Vj1jUoO75WGc9txWd311ZJJqS9Dr8QtNJJ7gk2r7dcM/yGe9sit7qOijQl3GAwhpBOz/W8CwkD7R6yob07nLbA==",
|
||||||
|
"requires": {
|
||||||
|
"@types/cookie": "^0.4.0",
|
||||||
|
"@types/cors": "^2.8.8",
|
||||||
|
"@types/node": "^14.14.7",
|
||||||
|
"accepts": "~1.3.4",
|
||||||
|
"base64id": "~2.0.0",
|
||||||
|
"debug": "~4.1.0",
|
||||||
|
"engine.io": "~4.0.0",
|
||||||
|
"socket.io-adapter": "~2.0.3",
|
||||||
|
"socket.io-parser": "~4.0.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": {
|
||||||
|
"version": "14.14.16",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.16.tgz",
|
||||||
|
"integrity": "sha512-naXYePhweTi+BMv11TgioE2/FXU4fSl29HAH1ffxVciNsH3rYXjNP2yM8wqmSm7jS20gM8TIklKiTen+1iVncw=="
|
||||||
|
},
|
||||||
|
"debug": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
|
||||||
|
"requires": {
|
||||||
|
"ms": "^2.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ms": {
|
||||||
|
"version": "2.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"socket.io-adapter": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-2wo4EXgxOGSFueqvHAdnmi5JLZzWqMArjuP4nqC26AtLh5PoCPsaRbRdah2xhcwTAMooZfjYiNVNkkmmSMaxOQ=="
|
||||||
|
},
|
||||||
|
"socket.io-parser": {
|
||||||
|
"version": "4.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.2.tgz",
|
||||||
|
"integrity": "sha512-Bs3IYHDivwf+bAAuW/8xwJgIiBNtlvnjYRc4PbXgniLmcP1BrakBoq/QhO24rgtgW7VZ7uAaswRGxutUnlAK7g==",
|
||||||
|
"requires": {
|
||||||
|
"@types/component-emitter": "^1.2.10",
|
||||||
|
"component-emitter": "~1.3.0",
|
||||||
|
"debug": "~4.1.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"debug": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
|
||||||
|
"requires": {
|
||||||
|
"ms": "^2.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ms": {
|
||||||
|
"version": "2.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"source-map": {
|
"source-map": {
|
||||||
"version": "0.6.1",
|
"version": "0.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||||
@@ -1753,6 +1914,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||||
},
|
},
|
||||||
|
"ws": {
|
||||||
|
"version": "7.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.1.tgz",
|
||||||
|
"integrity": "sha512-pTsP8UAfhy3sk1lSk/O/s4tjD0CRwvMnzvwr4OKGX7ZvqZtUyx4KIJB5JWbkykPoc55tixMGgTNoh3k4FkNGFQ=="
|
||||||
|
},
|
||||||
"yallist": {
|
"yallist": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
"jsonwebtoken": "^8.5.1",
|
"jsonwebtoken": "^8.5.1",
|
||||||
"mongoose": "^5.11.8",
|
"mongoose": "^5.11.8",
|
||||||
"mysql": "^2.18.1",
|
"mysql": "^2.18.1",
|
||||||
|
"socket.io": "^3.0.4",
|
||||||
"ts-node": "^9.1.1",
|
"ts-node": "^9.1.1",
|
||||||
"typescript": "^4.1.3",
|
"typescript": "^4.1.3",
|
||||||
"winston": "^3.3.3",
|
"winston": "^3.3.3",
|
||||||
@@ -46,6 +47,7 @@
|
|||||||
"@types/mysql": "2.15.16",
|
"@types/mysql": "2.15.16",
|
||||||
"@types/mongoose": "5.10.3",
|
"@types/mongoose": "5.10.3",
|
||||||
"@types/argon2": "0.15.0",
|
"@types/argon2": "0.15.0",
|
||||||
"@types/zeromq": "4.6.3"
|
"@types/zeromq": "4.6.3",
|
||||||
|
"@types/socket.io": "2.1.12"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { hashPassword, randomPepper, randomString } from './helper/crypto';
|
|||||||
import { InvoiceScheduler } from './helper/invoiceScheduler';
|
import { InvoiceScheduler } from './helper/invoiceScheduler';
|
||||||
import { User } from './models/user/user.model';
|
import { User } from './models/user/user.model';
|
||||||
import { invoiceRouter } from './routes/invoice';
|
import { invoiceRouter } from './routes/invoice';
|
||||||
|
import { userRouter } from './routes/user';
|
||||||
|
|
||||||
// Load .env
|
// Load .env
|
||||||
dconfig({ debug: true, encoding: 'UTF-8' });
|
dconfig({ debug: true, encoding: 'UTF-8' });
|
||||||
@@ -110,6 +111,7 @@ async function run() {
|
|||||||
|
|
||||||
app.get('/', (req, res) => res.status(200).send('OK'));
|
app.get('/', (req, res) => res.status(200).send('OK'));
|
||||||
app.use('/invoice', invoiceRouter);
|
app.use('/invoice', invoiceRouter);
|
||||||
|
app.use('/user', userRouter);
|
||||||
|
|
||||||
app.listen(config.http.port, config.http.host, () => {
|
app.listen(config.http.port, config.http.host, () => {
|
||||||
logger.info(`HTTP server started on port ${config.http.host}:${config.http.port}`);
|
logger.info(`HTTP server started on port ${config.http.host}:${config.http.port}`);
|
||||||
|
|||||||
@@ -77,3 +77,44 @@ export async function createInvoice(req: Request, res: Response) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GET /invoice/
|
||||||
|
// GET /invoice/:id
|
||||||
|
export async function getInvoice(req: Request, res: Response) {
|
||||||
|
const invoiceId = req.params.id;
|
||||||
|
|
||||||
|
// If an id is provided
|
||||||
|
if (invoiceId !== undefined) {
|
||||||
|
const invoice: any = await Invoice.findById(invoiceId);
|
||||||
|
if (invoice === null) {
|
||||||
|
res.status(404).send();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(200).send(invoice);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let skip = req.query.skip;
|
||||||
|
let limit = req.query.limit;
|
||||||
|
let sortQuery = req.query.sort; // Either 'newest' (DESC) or 'oldest' (ASC)
|
||||||
|
let sort = 1;
|
||||||
|
|
||||||
|
if (skip === undefined) skip = '0';
|
||||||
|
if (limit === undefined || Number(limit) > 100) limit = '100';
|
||||||
|
if (sortQuery !== undefined) {
|
||||||
|
if (sortQuery === 'newest') sort = -1;
|
||||||
|
else if (sortQuery === 'newest') sort = 1;
|
||||||
|
else {
|
||||||
|
res.status(400).send({ message: 'Unkown sort parameter. "sort" can only be "newest" or "oldest"' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const invoices = await Invoice.find({})
|
||||||
|
.limit(Number(limit))
|
||||||
|
.skip(Number(skip))
|
||||||
|
.sort({ createdAt: sort });
|
||||||
|
|
||||||
|
res.status(200).send(invoices);
|
||||||
|
}
|
||||||
142
src/controllers/user.ts
Normal file
142
src/controllers/user.ts
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
import { Request, Response } from 'express';
|
||||||
|
import { decode, sign, verify } from 'jsonwebtoken';
|
||||||
|
|
||||||
|
import { JWT_SECRET, logger } from '../app';
|
||||||
|
import * as jwt from 'jsonwebtoken';
|
||||||
|
import { config } from '../../config';
|
||||||
|
import { hashPassword, randomPepper, randomString, verifyPassword } from '../helper/crypto';
|
||||||
|
import { User } from '../models/user/user.model';
|
||||||
|
import { LibrePayRequest } from '../helper/request';
|
||||||
|
|
||||||
|
export async function getUser(req: LibrePayRequest, res: Response) {
|
||||||
|
let user: any = req.params.id === undefined ? req.user : await User.findById(req.params.id);
|
||||||
|
|
||||||
|
if (user === null) {
|
||||||
|
res.status(404).send();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
user.password = undefined;
|
||||||
|
user.salt = undefined;
|
||||||
|
user.__v = undefined;
|
||||||
|
|
||||||
|
res.status(200).send(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function createUser(req: LibrePayRequest, res: Response) {
|
||||||
|
const name = req.body.name;
|
||||||
|
const password = req.body.password;
|
||||||
|
const type = req.body.type;
|
||||||
|
|
||||||
|
if (name === undefined || password === undefined || type === undefined) {
|
||||||
|
res.status(400).send();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (await User.countDocuments({ name }) === 1) {
|
||||||
|
res.status(409).send();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const salt = randomString(config.authentification.salt_length);
|
||||||
|
const hashedPassword = await hashPassword(password + salt + randomPepper()).catch(error => {
|
||||||
|
res.status(400).send({ message: 'Provided password is too weak and cannot be used.' });
|
||||||
|
return;
|
||||||
|
}) as string;
|
||||||
|
|
||||||
|
const newUser = await User.create({
|
||||||
|
name,
|
||||||
|
password: hashedPassword,
|
||||||
|
salt,
|
||||||
|
lastLogin: new Date(0)
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create setup token that the new user can use to change his password.
|
||||||
|
const setupToken = jwt.sign({ setupForUser: newUser._id }, JWT_SECRET, { expiresIn: '1d' });
|
||||||
|
|
||||||
|
res.status(200).send({ setupToken });
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function DeleteUser(req: Request, res: Response) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function PatchUser(req: Request, res: Response) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function loginUser(req: Request, res: Response) {
|
||||||
|
const username = req.body.username;
|
||||||
|
const password = req.body.password;
|
||||||
|
const twoFA = req.body.twoFA;
|
||||||
|
|
||||||
|
const user = await User.findOne({ name: username });
|
||||||
|
|
||||||
|
// Check if user exists
|
||||||
|
if (user == undefined) {
|
||||||
|
setTimeout(() => {
|
||||||
|
res.status(404).send({ message: "Either the username or password is wrong." });
|
||||||
|
}, Math.random() * 1500 + 400);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if 2FA is turned on (the attack doesn't know yet if the password is wrong)
|
||||||
|
if (user.twoFASecret != undefined) {
|
||||||
|
if (twoFA == undefined) {
|
||||||
|
res.status(401).send({ message: "2FA code is required." });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// TODO: Implement 2FA logic here
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if password is wrong
|
||||||
|
if (!await verifyPassword(password + user.salt, user.password)) {
|
||||||
|
res.status(404).send({ message: 'Either the username or password is wrong.' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We're good. Create JWT token.
|
||||||
|
const token = sign({ user: user._id }, JWT_SECRET, { expiresIn: '30d' });
|
||||||
|
|
||||||
|
user.lastLogin = new Date(Date.now());
|
||||||
|
await user.save();
|
||||||
|
|
||||||
|
logger.info(`User ${user.name} logged in.`)
|
||||||
|
res.status(200).send({ token });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This middleware validates any tokens that are required to access most of the endpoints.
|
||||||
|
* Note: This validation doesn't contain any permission checking.
|
||||||
|
*/
|
||||||
|
export async function MW_User(req: LibrePayRequest, res: Response, next: () => void) {
|
||||||
|
if (req.headers.token === undefined) {
|
||||||
|
res.status(401).send({ message: "Token not specified" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const token = req.headers.token.toString();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Verify token
|
||||||
|
if(await verify(token, JWT_SECRET, { algorithms: ['HS256'] })) {
|
||||||
|
// Token is valid, now look if user is in db (in case he got deleted)
|
||||||
|
const id = decode(token, { json: true })!.user;
|
||||||
|
const db = await User.findById(id);
|
||||||
|
|
||||||
|
if (db !== undefined && db !== null) {
|
||||||
|
req.user = db
|
||||||
|
next();
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
res.status(401).send({ message: "Token is not valid" });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res.status(401).send({ message: "Token is not valid" });
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
if (err) {
|
||||||
|
res.status(500).send({ message: "We failed validating your token for some reason." });
|
||||||
|
logger.error(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -52,8 +52,6 @@ export class InvoiceScheduler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
decoded.result.vout.forEach(output => {
|
decoded.result.vout.forEach(output => {
|
||||||
//console.log('Output:', output.scriptPubKey);
|
|
||||||
|
|
||||||
// Loop over each output and check if the address of one matches the one of an invoice.
|
// Loop over each output and check if the address of one matches the one of an invoice.
|
||||||
this.pendingInvoices.forEach(invoice => {
|
this.pendingInvoices.forEach(invoice => {
|
||||||
// We found our transaction
|
// We found our transaction
|
||||||
|
|||||||
6
src/helper/request.ts
Normal file
6
src/helper/request.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { Request } from "express";
|
||||||
|
import { IUser } from "../models/user/user.interface";
|
||||||
|
|
||||||
|
export interface LibrePayRequest extends Request {
|
||||||
|
user?: IUser
|
||||||
|
}
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
import { Router } from "express";
|
import { Router } from "express";
|
||||||
import { createInvoice } from "../controllers/invoice";
|
import { createInvoice, getInvoice } from "../controllers/invoice";
|
||||||
|
import { MW_User } from "../controllers/user";
|
||||||
|
|
||||||
const invoiceRouter = Router()
|
const invoiceRouter = Router()
|
||||||
|
|
||||||
invoiceRouter.get('/:id');
|
invoiceRouter.get('/:id', getInvoice);
|
||||||
invoiceRouter.post('/', createInvoice);
|
invoiceRouter.get('/', MW_User, getInvoice);
|
||||||
|
invoiceRouter.post('/', MW_User, createInvoice);
|
||||||
|
|
||||||
export { invoiceRouter };
|
export { invoiceRouter };
|
||||||
10
src/routes/user.ts
Normal file
10
src/routes/user.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { Router } from "express";
|
||||||
|
import { MW_User, loginUser, getUser } from "../controllers/user";
|
||||||
|
|
||||||
|
const userRouter = Router()
|
||||||
|
|
||||||
|
userRouter.get('/login', loginUser);
|
||||||
|
userRouter.get('/', MW_User, getUser);
|
||||||
|
userRouter.get('/:id', MW_User, getUser);
|
||||||
|
|
||||||
|
export { userRouter };
|
||||||
Reference in New Issue
Block a user