From 64cb27eb45bb6c7f825ab046c9e896c223ceabc2 Mon Sep 17 00:00:00 2001 From: Kfir Dayan Date: Sun, 13 Aug 2023 11:51:54 +0300 Subject: [PATCH] first --- .DS_Store | Bin 0 -> 6148 bytes .gitignore | 5 + api/.env.example | 3 + api/README.md | 82 ++ api/package-lock.json | 1007 +++++++++++++++++ api/package.json | 21 + api/request.http | 12 + api/src/common/types/User.ts | 6 + .../controllers/DarioRegisterController.ts | 63 ++ api/src/db/mongodb/schema.ts | 46 + api/src/db/redis/Redis.ts | 78 ++ api/src/index.ts | 37 + api/src/middleware/register-middleware.ts | 12 + .../verify-eligibility-middleware.ts | 12 + api/src/models/DarioRegisterModel.ts | 72 ++ api/src/routers/DarioRegisterRouter.ts | 25 + api/tsconfig.json | 14 + infra/docker/docker-compose.yaml | 32 + infra/docker/mongo-init-scripts/init.js | 12 + inserter/.env.example | 5 + inserter/README.md | 47 + inserter/data.json | 122 ++ inserter/package-lock.json | 97 ++ inserter/package.json | 19 + inserter/src/common/types/User.ts | 7 + inserter/src/index.ts | 37 + inserter/src/redis/Redis.ts | 78 ++ inserter/tsconfig.json | 14 + 28 files changed, 1965 insertions(+) create mode 100644 .DS_Store create mode 100644 .gitignore create mode 100644 api/.env.example create mode 100644 api/README.md create mode 100644 api/package-lock.json create mode 100644 api/package.json create mode 100644 api/request.http create mode 100644 api/src/common/types/User.ts create mode 100644 api/src/controllers/DarioRegisterController.ts create mode 100644 api/src/db/mongodb/schema.ts create mode 100644 api/src/db/redis/Redis.ts create mode 100644 api/src/index.ts create mode 100644 api/src/middleware/register-middleware.ts create mode 100644 api/src/middleware/verify-eligibility-middleware.ts create mode 100644 api/src/models/DarioRegisterModel.ts create mode 100644 api/src/routers/DarioRegisterRouter.ts create mode 100644 api/tsconfig.json create mode 100644 infra/docker/docker-compose.yaml create mode 100644 infra/docker/mongo-init-scripts/init.js create mode 100644 inserter/.env.example create mode 100644 inserter/README.md create mode 100644 inserter/data.json create mode 100644 inserter/package-lock.json create mode 100644 inserter/package.json create mode 100644 inserter/src/common/types/User.ts create mode 100644 inserter/src/index.ts create mode 100644 inserter/src/redis/Redis.ts create mode 100644 inserter/tsconfig.json diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0= 0.6" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/bson": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-5.4.0.tgz", + "integrity": "sha512-WRZ5SQI5GfUuKnPTNmAYPiKIof3ORXAF4IRU5UcgmivNIon01rWQlw5RUH954dpu8yGL8T59YShVddIPaU/gFA==", + "engines": { + "node": ">=14.20.1" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/denque": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", + "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/dotenv": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/get-intrinsic": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/kareem": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz", + "integrity": "sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "optional": true + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mongodb": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.7.0.tgz", + "integrity": "sha512-zm82Bq33QbqtxDf58fLWBwTjARK3NSvKYjyz997KSy6hpat0prjeX/kxjbPVyZY60XYPDNETaHkHJI2UCzSLuw==", + "dependencies": { + "bson": "^5.4.0", + "mongodb-connection-string-url": "^2.6.0", + "socks": "^2.7.1" + }, + "engines": { + "node": ">=14.20.1" + }, + "optionalDependencies": { + "saslprep": "^1.0.3" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.201.0", + "@mongodb-js/zstd": "^1.1.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=2.3.0 <3", + "snappy": "^7.2.2" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + } + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz", + "integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==", + "dependencies": { + "@types/whatwg-url": "^8.2.1", + "whatwg-url": "^11.0.0" + } + }, + "node_modules/mongoose": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-7.4.2.tgz", + "integrity": "sha512-sNolW2hyncwvWmZjIEIwAckjaSKtC1SE86zE1v2TKm3vPTRogZfBQf+3zLYYdrgrVTzoaoICieVpct9hjcn3EQ==", + "dependencies": { + "bson": "^5.4.0", + "kareem": "2.5.1", + "mongodb": "5.7.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "16.0.1" + }, + "engines": { + "node": ">=14.20.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" + } + }, + "node_modules/mongoose/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "dependencies": { + "debug": "4.x" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/mquery/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/mquery/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/redis": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/redis/-/redis-3.1.2.tgz", + "integrity": "sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw==", + "dependencies": { + "denque": "^1.5.0", + "redis-commands": "^1.7.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-redis" + } + }, + "node_modules/redis-commands": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz", + "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==" + }, + "node_modules/redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "dependencies": { + "redis-errors": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/saslprep": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", + "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", + "optional": true, + "dependencies": { + "sparse-bitfield": "^3.0.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sift": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz", + "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==" + }, + "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/socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "optional": true, + "dependencies": { + "memory-pager": "^1.0.2" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + } + } +} diff --git a/api/package.json b/api/package.json new file mode 100644 index 0000000..771af92 --- /dev/null +++ b/api/package.json @@ -0,0 +1,21 @@ +{ + "name": "dario", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "dev": "nodemon dist/index.js" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "dotenv": "^16.3.1", + "express": "^4.18.2", + "mongoose": "^7.4.2", + "redis": "^3.1.2" + }, + "devDependencies": { + "@types/express": "^4.17.17" + } +} diff --git a/api/request.http b/api/request.http new file mode 100644 index 0000000..9ff13fe --- /dev/null +++ b/api/request.http @@ -0,0 +1,12 @@ +### Get +GET http://localhost:3000/ + + +### Post +POST http://localhost:3000/verify-eligibility +Content-Type: application/json + + +{ + "email": "kfda89@gmail.com" +} \ No newline at end of file diff --git a/api/src/common/types/User.ts b/api/src/common/types/User.ts new file mode 100644 index 0000000..ad64148 --- /dev/null +++ b/api/src/common/types/User.ts @@ -0,0 +1,6 @@ +export interface User { + Name: string; + Email: string; + Phone: string; + EmployeeID: string; +} \ No newline at end of file diff --git a/api/src/controllers/DarioRegisterController.ts b/api/src/controllers/DarioRegisterController.ts new file mode 100644 index 0000000..cf80802 --- /dev/null +++ b/api/src/controllers/DarioRegisterController.ts @@ -0,0 +1,63 @@ +import { NextFunction, Request, Response } from "express"; +import { Redis } from "../db/redis/Redis"; +import { RegisterModel } from "../models/DarioRegisterModel"; +import { User } from "../common/types/User"; + +export class DarioRegisterController { + redis: Redis; + registerModel: RegisterModel; + + constructor() { + this.redis = new Redis(); + this.registerModel = new RegisterModel(); + } + + async connectToRedis() { + await this.redis.connect(); + } + + public async verifyEligibility( + req: Request, + res: Response + ) { + const { key } = req.body; + try { + const user: any = await this.redis.findUserByKey(key); + res.status(200).json(user); + } catch (error) { + console.error(error.message); + res.status(500).send("Internal Server Error"); + } + } + + public async register(req: Request, res: Response, next: NextFunction) { + const { email, key, name, phone } = req.body; + try { + const user: any = await this.redis.findUserByKey(key); + if (!user) return res.status(404).send("User not found"); + + const isUserVerified: boolean = this.verifyUser(user, email, name, phone); + + if (isUserVerified) { + await this.registerModel.create(user); + await this.redis.deleteUserByKey(key); + res.status(200).send("User registered"); + } else { + res.status(404).send("User not found"); + } + } catch (error) { + console.error(error.message); + res.status(500).send("Internal Server Error"); + } + } + + private verifyUser( + user: User, + email: string, + name: string, + phone: string + ): boolean { + console.log(user.Phone !== phone); + return user.Email === email && user.Name.toLocaleLowerCase() === name.toLocaleLowerCase() && user.Phone === phone; + } +} diff --git a/api/src/db/mongodb/schema.ts b/api/src/db/mongodb/schema.ts new file mode 100644 index 0000000..1c7570d --- /dev/null +++ b/api/src/db/mongodb/schema.ts @@ -0,0 +1,46 @@ +import mongoose, { Document, Schema } from 'mongoose'; + +interface IUser extends Document { + Name: string; + Email: string; + Phone: string; + EmployeeID: string; + created_at: Date; + active: boolean; + updated_at: Date; +} + +const userSchema = new Schema({ + Name: { + type: String, + required: true, + }, + Email: { + type: String, + required: true, + }, + Phone: { + type: String, + required: true, + }, + EmployeeID: { + type: String, + required: true, + }, + created_at: { + type: Date, + default: Date.now, + }, + updated_at: { + type: Date, + default: Date.now, + }, + active: { + type: Boolean, + default: true, + }, +}); + +const UserModel = mongoose.model('User', userSchema); + +export default UserModel; diff --git a/api/src/db/redis/Redis.ts b/api/src/db/redis/Redis.ts new file mode 100644 index 0000000..ee128c8 --- /dev/null +++ b/api/src/db/redis/Redis.ts @@ -0,0 +1,78 @@ +import * as redis from "redis"; +import { User } from "../../common/types/User"; +import dotenv from "dotenv"; + +const envVars = dotenv.config().parsed; + + +class Redis { + client: any; + + async connect(): Promise { + this.client = redis.createClient({ url: envVars.REDIS_CONNECTION_URL }); + this.client.on("connect", () => { + console.log("Connected to Redis"); + }); + + this.client.on("error", (err) => { + console.log("Error connecting to Redis:", err); + process.exit(1); + }); + } + + public async findUserByKey(key: string) { + try { + this.connect(); + return new Promise((resolve, reject) => { + this.client.hget("users", key, (err: Error | null, userDataJson: string | null) => { + if (err) { + console.error("Error finding user in Redis:", err); + reject(err); + } else { + if (userDataJson) { + const userData: User = JSON.parse(userDataJson); + resolve(userData); + } else { + resolve(null); + } + } + }); + }); + } catch (error) { + console.error("Error connecting to Redis:", error); + throw error; + } finally { + this.close(); + } + } + + public async deleteUserByKey(key: string) { + try { + this.connect(); + return new Promise((resolve, reject) => { + this.client.hdel("users", key, (err: Error | null, userDataJson: string | null) => { + if (err) { + console.error("Error deleting user in Redis:", err); + reject(err); + } else { + console.log("User deleted") + resolve(null); + } + }); + }); + } catch (error) { + console.error("Error connecting to Redis:", error); + throw error; + } finally { + this.close(); + } + } + + + async close(): Promise { + await new Promise((resolve) => this.client.quit(resolve)); + console.log("Disconnected from Redis"); + } +} + +export { Redis }; diff --git a/api/src/index.ts b/api/src/index.ts new file mode 100644 index 0000000..db060cd --- /dev/null +++ b/api/src/index.ts @@ -0,0 +1,37 @@ +import express, { Express } from "express"; +import { router } from "./routers/DarioRegisterRouter"; +import dotenv from "dotenv"; + + +class App { + app: Express; + envVars: any; + + constructor() { + this.envVars = dotenv.config().parsed; + this.app = express(); + } + + public start() { + this.setMiddlewares(); + this.setRouters(); + this.startServer(); + } + + private setMiddlewares() { + this.app.use(express.json()); + } + + private startServer() { + this.app.listen(this.envVars.SERVER_PORT, () => { + console.log(`Server is running on port ${this.envVars.SERVER_PORT}`); + }); + } + + private setRouters() { + this.app.use(router); + } +} + +const app = new App(); +app.start(); diff --git a/api/src/middleware/register-middleware.ts b/api/src/middleware/register-middleware.ts new file mode 100644 index 0000000..9e1541c --- /dev/null +++ b/api/src/middleware/register-middleware.ts @@ -0,0 +1,12 @@ +export const registerMiddleware = async (req, res, next) => { + const { key, name, email, phone } = req.body; + try { + if (key && name && email && phone) { + next(); + } else { + next("key, name, email, and phone are required"); + } + } catch (error) { + next(error); + } +} \ No newline at end of file diff --git a/api/src/middleware/verify-eligibility-middleware.ts b/api/src/middleware/verify-eligibility-middleware.ts new file mode 100644 index 0000000..a68e7d8 --- /dev/null +++ b/api/src/middleware/verify-eligibility-middleware.ts @@ -0,0 +1,12 @@ +export const verifyEligibility = async (req, res, next) => { + const { key } = req.body; + try { + if (key) { + next(); + } else { + next("key is required"); + } + } catch (error) { + next(error); + } +}; diff --git a/api/src/models/DarioRegisterModel.ts b/api/src/models/DarioRegisterModel.ts new file mode 100644 index 0000000..7553aba --- /dev/null +++ b/api/src/models/DarioRegisterModel.ts @@ -0,0 +1,72 @@ +import UserModel from '../db/mongodb/schema'; // Import the user schema/model +import mongoose from 'mongoose'; +import { User } from '../common/types/User'; +import dotenv from 'dotenv'; + +const envVars = dotenv.config().parsed; + +export class RegisterModel { + + async connect() { + try { + await mongoose.connect(envVars.MONGO_CONNECTION_URL); + console.log('Connected to MongoDB'); + } catch (error) { + console.error('Error connecting to MongoDB:', error); + } + } + + async disconnect() { + try { + await mongoose.disconnect(); + console.log('Disconnected from MongoDB'); + } catch (error) { + console.error('Error disconnecting from MongoDB:', error); + } + } + + async create(userInput: User) { + try { + this.connect(); + const user = new UserModel(userInput); + console.log(user) + return await user.save(); + } catch (error) { + throw new Error('Error creating user: ' + error); + } finally { + this.disconnect(); + } + } + + async getByEmail(email: string) { + try { + return await UserModel.findOne({ Email: email }); + } catch (error) { + throw new Error('Error getting user by email: ' + error); + } + } + + async delete(email: string) { + try { + const user = await UserModel.findOne({ Email: email }); + if (user) { + user.active = false; + return await user.save(); + } + } catch (error) { + throw new Error('Error deleting user: ' + error); + } + } + + async updateUpdatedAt(email: string) { + try { + const user = await UserModel.findOne({ Email: email }); + if (user) { + user.updated_at = new Date(); + return await user.save(); + } + } catch (error) { + throw new Error('Error updating updated_at: ' + error); + } + } +} diff --git a/api/src/routers/DarioRegisterRouter.ts b/api/src/routers/DarioRegisterRouter.ts new file mode 100644 index 0000000..a5c66a9 --- /dev/null +++ b/api/src/routers/DarioRegisterRouter.ts @@ -0,0 +1,25 @@ +import express, { Response, Request, NextFunction } from "express"; +import { DarioRegisterController } from "../controllers/DarioRegisterController"; +import { verifyEligibility } from "../middleware/verify-eligibility-middleware"; +import { registerMiddleware } from "../middleware/register-middleware"; + +const router = express.Router(); +const controller = new DarioRegisterController(); + +router.post( + "/verify-eligibility", + verifyEligibility, + async (req: Request, res: Response) => { + await controller.verifyEligibility(req, res); + } +); + +router.post( + "/register", + registerMiddleware, + async (req: Request, res: Response, next: NextFunction) => { + await controller.register(req, res, next); + } +); + +export { router }; diff --git a/api/tsconfig.json b/api/tsconfig.json new file mode 100644 index 0000000..d8f127f --- /dev/null +++ b/api/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "module": "CommonJS", + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "target": "ES2019", + "moduleResolution": "node", + "outDir": "./dist", + "rootDir": "./src" + }, + "include": [ + "src/**/*" + ] +} \ No newline at end of file diff --git a/infra/docker/docker-compose.yaml b/infra/docker/docker-compose.yaml new file mode 100644 index 0000000..1e07403 --- /dev/null +++ b/infra/docker/docker-compose.yaml @@ -0,0 +1,32 @@ +version: "3" + +services: + redis: + image: redis:latest + container_name: my-redis + restart: always + ports: + - "6379:6379" + volumes: + - redis_data:/data + + mongodb: + image: arm64v8/mongo:4.0 + container_name: my-mongo + restart: always + ports: + - "27017:27017" + volumes: + - mongodb_data_vol:/data/db + - ./mongo-init-scripts/init.js:/docker-entrypoint-initdb.d/mongo-init.js + platform: linux/arm64/v8 + environment: + - MONGO_INITDB_DATABASE=admin + - MONGO_INITDB_ROOT_USERNAME=root + - MONGO_INITDB_ROOT_PASSWORD=root + expose: + - 27017 + +volumes: + redis_data: + mongodb_data_vol: diff --git a/infra/docker/mongo-init-scripts/init.js b/infra/docker/mongo-init-scripts/init.js new file mode 100644 index 0000000..f978a76 --- /dev/null +++ b/infra/docker/mongo-init-scripts/init.js @@ -0,0 +1,12 @@ +const username = 'example_user'; +const password = 'example_password'; +const dbName = 'example_db'; +const userRole = 'readWrite'; + +db = db.getSiblingDB(dbName); + +db.createUser({ + user: username, + pwd: password, + roles: [{ role: userRole, db: dbName }], +}); diff --git a/inserter/.env.example b/inserter/.env.example new file mode 100644 index 0000000..10aba4b --- /dev/null +++ b/inserter/.env.example @@ -0,0 +1,5 @@ +## Redis +REDIS_CONNECTION_URL="redis://localhost:6379" + +## SQS +SQS_URL="" diff --git a/inserter/README.md b/inserter/README.md new file mode 100644 index 0000000..3e3e494 --- /dev/null +++ b/inserter/README.md @@ -0,0 +1,47 @@ +### Inserter + +This is a program that inserts a data.json file into a redis database. + +## Usage + +To use this program, you must have a redis database running on your machine. You can download redis [here](https://redis.io/download). + +To run the program, you must have a data.json file in the same directory as the inserter.py file. The data.json file must be in the following format: + +``` +{ + "user1@example.com": { + "Name": "John Doe", + "Email": "user1@example.com", + "Phone": "555-1234", + "EmployeeID": "EMP001" + }, + "user2@example.com": { + "Name": "Jane Smith", + "Email": "user2@example.com", + "Phone": "444-5678", + "EmployeeID": "EMP002" + }, +} +``` + +## Install +``` +npm install +``` +## ENV +``` +export REDIS_CONNECTION_URL=redis://localhost:6379 +``` +Or use the .env.example file + +## Run +``` +npm run dev +``` + +## Output +This program will remove all in redis and insert new data by the data.json file. +the users collection will be inserted in a transaction mode with the redis database, with expiration of 4 days. + + diff --git a/inserter/data.json b/inserter/data.json new file mode 100644 index 0000000..a0b103e --- /dev/null +++ b/inserter/data.json @@ -0,0 +1,122 @@ +{ + "user1@example.com": { + "Name": "John Doe", + "Email": "user1@example.com", + "Phone": "555-1234", + "EmployeeID": "EMP001" + }, + "user2@example.com": { + "Name": "Jane Smith", + "Email": "user2@example.com", + "Phone": "444-5678", + "EmployeeID": "EMP002" + }, + "user3@example.com": { + "Name": "Michael Johnson", + "Email": "user3@example.com", + "Phone": "777-9876", + "EmployeeID": "EMP003" + }, + "user4@example.com": { + "Name": "Emily Wilson", + "Email": "user4@example.com", + "Phone": "999-5432", + "EmployeeID": "EMP004" + }, + "user5@example.com": { + "Name": "David Lee", + "Email": "user5@example.com", + "Phone": "111-2222", + "EmployeeID": "EMP005" + }, + "user6@example.com": { + "Name": "Olivia Martinez", + "Email": "user6@example.com", + "Phone": "888-7654", + "EmployeeID": "EMP006" + }, + "user7@example.com": { + "Name": "William Taylor", + "Email": "user7@example.com", + "Phone": "777-8888", + "EmployeeID": "EMP007" + }, + "user8@example.com": { + "Name": "Sophia Anderson", + "Email": "user8@example.com", + "Phone": "333-4444", + "EmployeeID": "EMP008" + }, + "user9@example.com": { + "Name": "James Brown", + "Email": "user9@example.com", + "Phone": "222-1111", + "EmployeeID": "EMP009" + }, + "user10@example.com": { + "Name": "Isabella Garcia", + "Email": "user10@example.com", + "Phone": "111-9999", + "EmployeeID": "EMP010" + }, + "user11@example.com": { + "Name": "Ethan Clark", + "Email": "user11@example.com", + "Phone": "666-7777", + "EmployeeID": "EMP011" + }, + "user12@example.com": { + "Name": "Ava Hernandez", + "Email": "user12@example.com", + "Phone": "777-4444", + "EmployeeID": "EMP012" + }, + "user13@example.com": { + "Name": "Alexander Allen", + "Email": "user13@example.com", + "Phone": "999-2222", + "EmployeeID": "EMP013" + }, + "user14@example.com": { + "Name": "Mia Turner", + "Email": "user14@example.com", + "Phone": "333-5555", + "EmployeeID": "EMP014" + }, + "user15@example.com": { + "Name": "Benjamin Scott", + "Email": "user15@example.com", + "Phone": "222-7777", + "EmployeeID": "EMP015" + }, + "user16@example.com": { + "Name": "Amelia Adams", + "Email": "user16@example.com", + "Phone": "777-3333", + "EmployeeID": "EMP016" + }, + "user17@example.com": { + "Name": "Daniel Evans", + "Email": "user17@example.com", + "Phone": "444-1111", + "EmployeeID": "EMP017" + }, + "user18@example.com": { + "Name": "Charlotte Stewart", + "Email": "user18@example.com", + "Phone": "888-6666", + "EmployeeID": "EMP018" + }, + "user19@example.com": { + "Name": "Logan Hernandez", + "Email": "user19@example.com", + "Phone": "666-4444", + "EmployeeID": "EMP019" + }, + "user20@example.com": { + "Name": "Scarlett Parker", + "Email": "user20@example.com", + "Phone": "222-8888", + "EmployeeID": "EMP020" + } +} diff --git a/inserter/package-lock.json b/inserter/package-lock.json new file mode 100644 index 0000000..da76904 --- /dev/null +++ b/inserter/package-lock.json @@ -0,0 +1,97 @@ +{ + "name": "inserter", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "inserter", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@types/redis": "^4.0.11", + "dotenv": "^16.3.1", + "redis": "^3.1.2" + }, + "devDependencies": { + "@types/node": "^20.4.8" + } + }, + "node_modules/@types/node": { + "version": "20.4.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.8.tgz", + "integrity": "sha512-0mHckf6D2DiIAzh8fM8f3HQCvMKDpK94YQ0DSVkfWTG9BZleYIWudw9cJxX8oCk9bM+vAkDyujDV6dmKHbvQpg==", + "dev": true + }, + "node_modules/@types/redis": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/@types/redis/-/redis-4.0.11.tgz", + "integrity": "sha512-bI+gth8La8Wg/QCR1+V1fhrL9+LZUSWfcqpOj2Kc80ZQ4ffbdL173vQd5wovmoV9i071FU9oP2g6etLuEwb6Rg==", + "deprecated": "This is a stub types definition. redis provides its own type definitions, so you do not need this installed.", + "dependencies": { + "redis": "*" + } + }, + "node_modules/denque": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", + "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/dotenv": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, + "node_modules/redis": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/redis/-/redis-3.1.2.tgz", + "integrity": "sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw==", + "dependencies": { + "denque": "^1.5.0", + "redis-commands": "^1.7.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-redis" + } + }, + "node_modules/redis-commands": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz", + "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==" + }, + "node_modules/redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "dependencies": { + "redis-errors": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + } + } +} diff --git a/inserter/package.json b/inserter/package.json new file mode 100644 index 0000000..bf0de3a --- /dev/null +++ b/inserter/package.json @@ -0,0 +1,19 @@ +{ + "name": "inserter", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "dev": "nodemon dist/index.js" + }, + "author": "", + "license": "ISC", + "devDependencies": { + "@types/node": "^20.4.8" + }, + "dependencies": { + "@types/redis": "^4.0.11", + "dotenv": "^16.3.1", + "redis": "^3.1.2" + } +} diff --git a/inserter/src/common/types/User.ts b/inserter/src/common/types/User.ts new file mode 100644 index 0000000..d407dd7 --- /dev/null +++ b/inserter/src/common/types/User.ts @@ -0,0 +1,7 @@ +export interface User { + Name: string; + Email: string; + Phone: string; + EmployeeID: string; + SecureKey?: string; +} \ No newline at end of file diff --git a/inserter/src/index.ts b/inserter/src/index.ts new file mode 100644 index 0000000..64d8d9d --- /dev/null +++ b/inserter/src/index.ts @@ -0,0 +1,37 @@ +import { Redis } from "./redis/Redis"; +import fs from "fs"; +import { User } from "./common/types/User"; + +class Inserter { + redis: Redis; + + constructor() { + console.log("Inserter class is created"); + this.redis = new Redis(); + } + + async connectToRedis() { + await this.redis.connect(); + } + + async start() { + try { + await this.connectToRedis(); + const data = await this.readFile("./data.json"); + await this.redis.transactionToRedis(data); + } catch (error) { + console.error("Error:", error); + } finally { + this.redis.close(); + } + } + + async readFile(filePath: string): Promise { + const data = fs.readFileSync(filePath, "utf8"); + const json = JSON.parse(data); + return json; + } +} + +const inserter = new Inserter(); +inserter.start(); diff --git a/inserter/src/redis/Redis.ts b/inserter/src/redis/Redis.ts new file mode 100644 index 0000000..b5ab210 --- /dev/null +++ b/inserter/src/redis/Redis.ts @@ -0,0 +1,78 @@ +import * as redis from "redis"; +import { User } from "../common/types/User"; +import { randomUUID } from "crypto"; +import dotenv from "dotenv"; + + +class Redis { + client: any; + envVars: any; + + constructor() { + this.envVars = dotenv.config().parsed; + console.log("Redis class is created"); + } + + async connect(): Promise { + this.client = redis.createClient({ url: this.envVars.REDIS_CONNECTION_URL }); + this.client.on("connect", () => { + console.log("Connected to Redis"); + }); + + this.client.on("error", (err) => { + console.log("Error connecting to Redis:", err); + process.exit(1); + }); + } + + async transactionToRedis(data: User[]): Promise { + const EXPIRATION_TIME = 60 * 60 * 24 * 4; + + const multi = this.client.multi(); + multi.flushall(); + + for (const user in data) { + if (!data[user].EmployeeID || !data[user].Email || !data[user].Name || !data[user].Phone) { + this.rollback("Invalid user data", user); + return; + } + data[user].SecureKey = this.randomUUID() + data[user].Email = this.encrypt(data[user].Email) + multi.expire("users", EXPIRATION_TIME); + multi.hset("users", data[user].SecureKey, JSON.stringify(data[user])); + }; + + multi.exec(async (err: any, replies: any) => { + if (err) { + console.log("Error inserting data in Redis:", err.message); + } else { + console.log("Data inserted in Redis:", replies); + await this.pushToSqs(data); + } + }); + } + + rollback(reason: string, session: any, data = null): void { + console.error(reason, data); + session.discard(); + } + + randomUUID(): string { + return randomUUID(); + } + + private encrypt(email: string): string { + return email; + } + + async close(): Promise { + await new Promise((resolve) => this.client.quit(resolve)); + console.log("Disconnected from Redis"); + } + + private async pushToSqs(data: User[]): Promise { + console.log("Pushing to SQS"); + } +} + +export { Redis }; diff --git a/inserter/tsconfig.json b/inserter/tsconfig.json new file mode 100644 index 0000000..d8f127f --- /dev/null +++ b/inserter/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "module": "CommonJS", + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "target": "ES2019", + "moduleResolution": "node", + "outDir": "./dist", + "rootDir": "./src" + }, + "include": [ + "src/**/*" + ] +} \ No newline at end of file