parent
55083bb1b3
commit
2dd6c9f6b4
20 changed files with 832 additions and 110 deletions
.env.example
frontend/src/models
package-lock.jsonpackage.jsonsrc
|
@ -75,7 +75,7 @@ DB_LOCATION__COUNTRY=country
|
|||
|
||||
# The name of the column that contains the postal code of each location point
|
||||
# Comment or leave empty if the postal code is not available.
|
||||
DB_LOCATION__POSTAL_CODE=postal_code
|
||||
DB_LOCATION__POSTAL_CODE=postalCode
|
||||
|
||||
###
|
||||
### Frontend configuration
|
||||
|
|
|
@ -7,7 +7,6 @@ class User {
|
|||
public firstName: Optional<string>;
|
||||
public lastName: Optional<string>;
|
||||
public createdAt: Optional<Date>;
|
||||
public updatedAt: Optional<Date>;
|
||||
|
||||
constructor(user: {
|
||||
id: number;
|
||||
|
@ -16,7 +15,6 @@ class User {
|
|||
firstName?: string;
|
||||
lastName?: string;
|
||||
createdAt?: Date;
|
||||
updatedAt?: Date;
|
||||
}) {
|
||||
this.id = user.id;
|
||||
this.username = user.username;
|
||||
|
@ -24,7 +22,6 @@ class User {
|
|||
this.firstName = user.firstName || null;
|
||||
this.lastName = user.lastName || null;
|
||||
this.createdAt = user.createdAt || null;
|
||||
this.updatedAt = user.updatedAt || null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,20 +4,17 @@ class UserSession {
|
|||
public id: string;
|
||||
public userId: number;
|
||||
public createdAt: Date;
|
||||
public updatedAt: Date;
|
||||
public expiresAt: Optional<Date>;
|
||||
|
||||
constructor(userSession: {
|
||||
id: string;
|
||||
userId: number;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
expiresAt?: Date;
|
||||
}) {
|
||||
this.id = userSession.id;
|
||||
this.userId = userSession.userId;
|
||||
this.createdAt = userSession.createdAt;
|
||||
this.updatedAt = userSession.updatedAt;
|
||||
this.expiresAt = userSession.expiresAt || null;
|
||||
}
|
||||
}
|
||||
|
|
509
package-lock.json
generated
509
package-lock.json
generated
|
@ -18,6 +18,7 @@
|
|||
"pg": "^8.13.3",
|
||||
"sequelize": "^6.37.5",
|
||||
"sqlite3": "^5.1.7",
|
||||
"umzug": "^3.8.2",
|
||||
"uuid": "^11.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -36,6 +37,41 @@
|
|||
"license": "MIT",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||
"integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@nodelib/fs.stat": "2.0.5",
|
||||
"run-parallel": "^1.1.9"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/@nodelib/fs.stat": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
|
||||
"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/@nodelib/fs.walk": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
|
||||
"integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@nodelib/fs.scandir": "2.1.5",
|
||||
"fastq": "^1.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/@npmcli/fs": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz",
|
||||
|
@ -62,6 +98,99 @@
|
|||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@rushstack/node-core-library": {
|
||||
"version": "5.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-5.11.0.tgz",
|
||||
"integrity": "sha512-I8+VzG9A0F3nH2rLpPd7hF8F7l5Xb7D+ldrWVZYegXM6CsKkvWc670RlgK3WX8/AseZfXA/vVrh0bpXe2Y2UDQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ajv": "~8.13.0",
|
||||
"ajv-draft-04": "~1.0.0",
|
||||
"ajv-formats": "~3.0.1",
|
||||
"fs-extra": "~11.3.0",
|
||||
"import-lazy": "~4.0.0",
|
||||
"jju": "~1.4.0",
|
||||
"resolve": "~1.22.1",
|
||||
"semver": "~7.5.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/node": "*"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/node": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@rushstack/node-core-library/node_modules/semver": {
|
||||
"version": "7.5.4",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
||||
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@rushstack/terminal": {
|
||||
"version": "0.15.0",
|
||||
"resolved": "https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.15.0.tgz",
|
||||
"integrity": "sha512-vXQPRQ+vJJn4GVqxkwRe+UGgzNxdV8xuJZY2zem46Y0p3tlahucH9/hPmLGj2i9dQnUBFiRnoM9/KW7PYw8F4Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@rushstack/node-core-library": "5.11.0",
|
||||
"supports-color": "~8.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/node": "*"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/node": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@rushstack/terminal/node_modules/has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@rushstack/terminal/node_modules/supports-color": {
|
||||
"version": "8.1.1",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
|
||||
"integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"has-flag": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/supports-color?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@rushstack/ts-command-line": {
|
||||
"version": "4.23.5",
|
||||
"resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.23.5.tgz",
|
||||
"integrity": "sha512-jg70HfoK44KfSP3MTiL5rxsZH7X1ktX3cZs9Sl8eDu1/LxJSbPsh0MOFRC710lIuYYSgxWjI5AjbCBAl7u3RxA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@rushstack/terminal": "0.15.0",
|
||||
"@types/argparse": "1.0.38",
|
||||
"argparse": "~1.0.9",
|
||||
"string-argv": "~0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@tootallnate/once": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
|
||||
|
@ -72,6 +201,12 @@
|
|||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/argparse": {
|
||||
"version": "1.0.38",
|
||||
"resolved": "https://registry.npmjs.org/@types/argparse/-/argparse-1.0.38.tgz",
|
||||
"integrity": "sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/body-parser": {
|
||||
"version": "1.19.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz",
|
||||
|
@ -306,6 +441,53 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/ajv": {
|
||||
"version": "8.13.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.13.0.tgz",
|
||||
"integrity": "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"json-schema-traverse": "^1.0.0",
|
||||
"require-from-string": "^2.0.2",
|
||||
"uri-js": "^4.4.1"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/epoberezkin"
|
||||
}
|
||||
},
|
||||
"node_modules/ajv-draft-04": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz",
|
||||
"integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"ajv": "^8.5.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"ajv": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/ajv-formats": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz",
|
||||
"integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ajv": "^8.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"ajv": "^8.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"ajv": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-regex": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
|
@ -352,6 +534,21 @@
|
|||
"node": "^12.13.0 || ^14.15.0 || >=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/argparse": {
|
||||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
||||
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"sprintf-js": "~1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/argparse/node_modules/sprintf-js": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/array-flatten": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
||||
|
@ -466,7 +663,6 @@
|
|||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
||||
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fill-range": "^7.1.1"
|
||||
|
@ -805,6 +1001,18 @@
|
|||
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/emittery": {
|
||||
"version": "0.13.1",
|
||||
"resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz",
|
||||
"integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sindresorhus/emittery?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
|
@ -970,6 +1178,37 @@
|
|||
"url": "https://opencollective.com/express"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-glob": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
|
||||
"integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@nodelib/fs.stat": "^2.0.2",
|
||||
"@nodelib/fs.walk": "^1.2.3",
|
||||
"glob-parent": "^5.1.2",
|
||||
"merge2": "^1.3.0",
|
||||
"micromatch": "^4.0.8"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fastq": {
|
||||
"version": "1.19.1",
|
||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz",
|
||||
"integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"reusify": "^1.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/file-uri-to-path": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
|
||||
|
@ -980,7 +1219,6 @@
|
|||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
|
@ -1031,6 +1269,20 @@
|
|||
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fs-extra": {
|
||||
"version": "11.3.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz",
|
||||
"integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.14"
|
||||
}
|
||||
},
|
||||
"node_modules/fs-minipass": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
|
||||
|
@ -1164,7 +1416,6 @@
|
|||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"is-glob": "^4.0.1"
|
||||
|
@ -1189,8 +1440,7 @@
|
|||
"version": "4.2.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
||||
"license": "ISC",
|
||||
"optional": true
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/has-flag": {
|
||||
"version": "3.0.0",
|
||||
|
@ -1384,6 +1634,15 @@
|
|||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/import-lazy": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz",
|
||||
"integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/imurmurhash": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
|
||||
|
@ -1480,11 +1739,25 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/is-core-module": {
|
||||
"version": "2.16.1",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
|
||||
"integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"hasown": "^2.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/is-extglob": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
|
@ -1504,7 +1777,6 @@
|
|||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-extglob": "^2.1.1"
|
||||
|
@ -1524,7 +1796,6 @@
|
|||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.12.0"
|
||||
|
@ -1537,6 +1808,12 @@
|
|||
"license": "ISC",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/jju": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz",
|
||||
"integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/jsbn": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
|
||||
|
@ -1544,6 +1821,24 @@
|
|||
"license": "MIT",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/json-schema-traverse": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/jsonwebtoken": {
|
||||
"version": "9.0.2",
|
||||
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz",
|
||||
|
@ -1646,7 +1941,6 @@
|
|||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"license": "ISC",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
|
@ -1709,6 +2003,15 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/merge2": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
||||
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/methods": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
|
||||
|
@ -1718,6 +2021,19 @@
|
|||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/micromatch": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
|
||||
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"braces": "^3.0.3",
|
||||
"picomatch": "^2.3.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
|
||||
|
@ -2157,6 +2473,12 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/path-parse": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/path-to-regexp": {
|
||||
"version": "0.1.12",
|
||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
|
||||
|
@ -2256,7 +2578,6 @@
|
|||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8.6"
|
||||
|
@ -2265,6 +2586,15 @@
|
|||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/pony-cause": {
|
||||
"version": "2.1.11",
|
||||
"resolved": "https://registry.npmjs.org/pony-cause/-/pony-cause-2.1.11.tgz",
|
||||
"integrity": "sha512-M7LhCsdNbNgiLYiP4WjsfLUuFmCfnjdF6jKe2R9NKl4WFN+HZPGHJZ9lnLP7f9ZnKe3U9nuWD0szirmj+migUg==",
|
||||
"license": "0BSD",
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/postgres-array": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
|
||||
|
@ -2381,6 +2711,15 @@
|
|||
"once": "^1.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/qs": {
|
||||
"version": "6.13.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
|
||||
|
@ -2396,6 +2735,26 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/queue-microtask": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
||||
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/range-parser": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
||||
|
@ -2462,6 +2821,35 @@
|
|||
"node": ">=8.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/require-from-string": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
|
||||
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/resolve": {
|
||||
"version": "1.22.10",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
|
||||
"integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-core-module": "^2.16.0",
|
||||
"path-parse": "^1.0.7",
|
||||
"supports-preserve-symlinks-flag": "^1.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"resolve": "bin/resolve"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/retry": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
|
||||
|
@ -2478,6 +2866,16 @@
|
|||
"integrity": "sha512-XgmCoxKWkDofwH8WddD0w85ZfqYz+ZHlr5yo+3YUCfycWawU56T5ckWXsScsj5B8tqUcIG67DxXByo3VUgiAdA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/reusify": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
|
||||
"integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"iojs": ">=1.0.0",
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/rimraf": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||
|
@ -2495,6 +2893,29 @@
|
|||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/run-parallel": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
|
||||
"integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"queue-microtask": "^1.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
|
@ -2977,6 +3398,15 @@
|
|||
"safe-buffer": "~5.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/string-argv": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz",
|
||||
"integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.6.19"
|
||||
}
|
||||
},
|
||||
"node_modules/string-width": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||
|
@ -3027,6 +3457,18 @@
|
|||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/supports-preserve-symlinks-flag": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
|
||||
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/tar": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
|
||||
|
@ -3091,7 +3533,6 @@
|
|||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-number": "^7.0.0"
|
||||
|
@ -3137,6 +3578,18 @@
|
|||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/type-fest": {
|
||||
"version": "4.37.0",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.37.0.tgz",
|
||||
"integrity": "sha512-S/5/0kFftkq27FPNye0XM1e2NsnoD/3FS+pBmbjmmtLT6I+i344KoOf7pvXreaFsDamWeaJX55nczA1m5PsBDg==",
|
||||
"license": "(MIT OR CC0-1.0)",
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/type-is": {
|
||||
"version": "1.6.18",
|
||||
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
|
||||
|
@ -3164,6 +3617,22 @@
|
|||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/umzug": {
|
||||
"version": "3.8.2",
|
||||
"resolved": "https://registry.npmjs.org/umzug/-/umzug-3.8.2.tgz",
|
||||
"integrity": "sha512-BEWEF8OJjTYVC56GjELeHl/1XjFejrD7aHzn+HldRJTx+pL1siBrKHZC8n4K/xL3bEzVA9o++qD1tK2CpZu4KA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@rushstack/ts-command-line": "^4.12.2",
|
||||
"emittery": "^0.13.0",
|
||||
"fast-glob": "^3.3.2",
|
||||
"pony-cause": "^2.1.4",
|
||||
"type-fest": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/undefsafe": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
|
||||
|
@ -3197,6 +3666,15 @@
|
|||
"imurmurhash": "^0.1.4"
|
||||
}
|
||||
},
|
||||
"node_modules/universalify": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
|
||||
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/unpipe": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||
|
@ -3206,6 +3684,15 @@
|
|||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/uri-js": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
"pg": "^8.13.3",
|
||||
"sequelize": "^6.37.5",
|
||||
"sqlite3": "^5.1.7",
|
||||
"umzug": "^3.8.2",
|
||||
"uuid": "^11.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -18,8 +18,11 @@ class App {
|
|||
}: any) {
|
||||
useGlobals();
|
||||
$db.sync().then(() => {
|
||||
$repos.userRoles.init();
|
||||
$repos.users.syncAdminUser();
|
||||
$repos.userRoles.init().then(() => {
|
||||
$repos.users.syncAdminUser().then(() => {
|
||||
console.log(' The database is ready');
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
this.app = app;
|
||||
|
|
77
src/db/Db.ts
77
src/db/Db.ts
|
@ -1,21 +1,25 @@
|
|||
import { Sequelize, Dialect } from 'sequelize';
|
||||
|
||||
import Migrations from './Migrations';
|
||||
|
||||
import GPSData from './types/GPSData';
|
||||
import Role from './types/Role';
|
||||
import User from './types/User';
|
||||
import UserDevice from './types/UserDevice';
|
||||
import UserRole from './types/UserRole';
|
||||
import UserSession from './types/UserSession';
|
||||
|
||||
class Db {
|
||||
private readonly url: string;
|
||||
private readonly locationUrl: string;
|
||||
private readonly locationTable: string;
|
||||
public readonly url: string;
|
||||
public readonly locationUrl: string;
|
||||
public readonly locationTable: string;
|
||||
public readonly locationTableColumns: Record<string, string>;
|
||||
private readonly dialect: Dialect;
|
||||
private readonly locationDialect: Dialect;
|
||||
private readonly tablePrefix: string;
|
||||
private readonly appDb: Sequelize;
|
||||
private readonly locationDb: Sequelize;
|
||||
private readonly migrations: Migrations;
|
||||
|
||||
private static readonly envColumnPrefix = 'DB_LOCATION__';
|
||||
|
||||
|
@ -51,6 +55,8 @@ class Db {
|
|||
logging: process.env.DEBUG === 'true' ? console.log : false
|
||||
});
|
||||
}
|
||||
|
||||
this.migrations = new Migrations(this.appDb);
|
||||
}
|
||||
|
||||
public static fromEnv(): Db {
|
||||
|
@ -87,7 +93,7 @@ class Db {
|
|||
'address',
|
||||
'locality',
|
||||
'country',
|
||||
'postal_code'
|
||||
'postalCode'
|
||||
].reduce((acc: any, name: string) => {
|
||||
acc[name] = process.env[this.prefixedEnv(name)];
|
||||
if (!acc[name]?.length && requiredColumns[name]) {
|
||||
|
@ -111,51 +117,10 @@ class Db {
|
|||
|
||||
public async sync() {
|
||||
console.log('Syncing databases');
|
||||
|
||||
for (const modelName of ['GPSData', 'Role', 'User', 'UserRole', 'UserSession']) {
|
||||
const model = (this as any)[modelName]();
|
||||
process.stdout.write(` [⌛] Syncing ${model.name}`);
|
||||
await model.sync();
|
||||
await this.appDb.sync();
|
||||
process.stdout.write(`\r [✅] Synced ${model.name} \n`);
|
||||
}
|
||||
|
||||
this.initConstraints();
|
||||
await this.migrations.up();
|
||||
console.log('Database sync completed');
|
||||
}
|
||||
|
||||
private initConstraints() {
|
||||
this.appDb.models.UserSession.belongsTo(this.appDb.models.User, {
|
||||
foreignKey: 'userId',
|
||||
targetKey: 'id',
|
||||
as: 'user',
|
||||
onDelete: 'CASCADE'
|
||||
});
|
||||
|
||||
this.appDb.models.User.hasMany(this.appDb.models.UserSession, {
|
||||
foreignKey: 'userId',
|
||||
sourceKey: 'id',
|
||||
as: 'sessions'
|
||||
});
|
||||
|
||||
this.appDb.models.User.belongsToMany(this.appDb.models.Role, {
|
||||
through: this.appDb.models.UserRole,
|
||||
foreignKey: 'userId',
|
||||
otherKey: 'roleId',
|
||||
as: 'roles'
|
||||
});
|
||||
|
||||
this.appDb.models.Role.belongsToMany(this.appDb.models.User, {
|
||||
through: this.appDb.models.UserRole,
|
||||
foreignKey: 'roleId',
|
||||
otherKey: 'userId',
|
||||
as: 'users'
|
||||
});
|
||||
|
||||
this.appDb.models.UserSession.sync();
|
||||
this.appDb.sync();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tables
|
||||
*/
|
||||
|
@ -176,31 +141,27 @@ class Db {
|
|||
|
||||
public User() {
|
||||
return this.appDb.define('User', User(), {
|
||||
indexes: [
|
||||
{
|
||||
unique: true,
|
||||
fields: ['username', 'email'],
|
||||
},
|
||||
],
|
||||
tableName: this.tableName('users'),
|
||||
timestamps: false,
|
||||
});
|
||||
}
|
||||
|
||||
public UserDevice() {
|
||||
return this.appDb.define('UserDevice', UserDevice(), {
|
||||
tableName: this.tableName('user_devices'),
|
||||
timestamps: false,
|
||||
});
|
||||
}
|
||||
|
||||
public UserRole() {
|
||||
return this.appDb.define('UserRole', UserRole(), {
|
||||
tableName: this.tableName('user_roles'),
|
||||
tableName: this.tableName('users_roles'),
|
||||
timestamps: false,
|
||||
});
|
||||
}
|
||||
|
||||
public UserSession() {
|
||||
const ret = this.appDb.define('UserSession', UserSession(), {
|
||||
indexes: [
|
||||
{
|
||||
fields: ['userId'],
|
||||
},
|
||||
],
|
||||
tableName: this.tableName('user_sessions'),
|
||||
timestamps: false,
|
||||
});
|
||||
|
|
23
src/db/Migrations.ts
Normal file
23
src/db/Migrations.ts
Normal file
|
@ -0,0 +1,23 @@
|
|||
import { Sequelize, } from 'sequelize';
|
||||
import { Umzug, SequelizeStorage, } from 'umzug';
|
||||
|
||||
class Migrations {
|
||||
private readonly migrations: Umzug;
|
||||
|
||||
constructor(db: Sequelize) {
|
||||
this.migrations = new Umzug({
|
||||
storage: new SequelizeStorage({ sequelize: db }),
|
||||
context: db.getQueryInterface(),
|
||||
migrations: {
|
||||
glob: 'src/db/migrations/*.*s',
|
||||
},
|
||||
logger: console,
|
||||
}) as Umzug;
|
||||
}
|
||||
|
||||
public async up(): Promise<void> {
|
||||
await this.migrations.up();
|
||||
}
|
||||
}
|
||||
|
||||
export default Migrations;
|
243
src/db/migrations/000_initial.ts
Normal file
243
src/db/migrations/000_initial.ts
Normal file
|
@ -0,0 +1,243 @@
|
|||
const { DataTypes } = require('sequelize');
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
|
||||
async function createLocationHistoryTable(query: { context: any }) {
|
||||
// Only create the table if locationUrl == appUrl (i.e. the location is stored
|
||||
// on the app managed database and not on an external one)
|
||||
if ($db.locationUrl !== $db.url) {
|
||||
console.log('The location history table is stored on an external database, skipping creation');
|
||||
return;
|
||||
}
|
||||
|
||||
const typeDef: Record<string, any> = {
|
||||
[$db.locationTableColumns['id']]: {
|
||||
type: DataTypes.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true
|
||||
},
|
||||
[$db.locationTableColumns['latitude']]: {
|
||||
type: DataTypes.FLOAT,
|
||||
allowNull: false
|
||||
},
|
||||
[$db.locationTableColumns['longitude']]: {
|
||||
type: DataTypes.FLOAT,
|
||||
allowNull: false
|
||||
},
|
||||
[$db.locationTableColumns['timestamp']]: {
|
||||
type: DataTypes.DATE,
|
||||
defaultValue: DataTypes.NOW,
|
||||
allowNull: false
|
||||
},
|
||||
}
|
||||
|
||||
if ($db.locationTableColumns['altitude']) {
|
||||
typeDef[$db.locationTableColumns['altitude']] = {
|
||||
type: DataTypes.FLOAT,
|
||||
allowNull: true
|
||||
}
|
||||
}
|
||||
|
||||
if ($db.locationTableColumns['address']) {
|
||||
typeDef[$db.locationTableColumns['address']] = {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true
|
||||
}
|
||||
}
|
||||
|
||||
if ($db.locationTableColumns['locality']) {
|
||||
typeDef[$db.locationTableColumns['locality']] = {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true
|
||||
}
|
||||
}
|
||||
|
||||
if ($db.locationTableColumns['country']) {
|
||||
typeDef[$db.locationTableColumns['country']] = {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true
|
||||
}
|
||||
}
|
||||
|
||||
if ($db.locationTableColumns['postalCode']) {
|
||||
typeDef[$db.locationTableColumns['postalCode']] = {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true
|
||||
}
|
||||
}
|
||||
|
||||
await query.context.createTable($db.locationTable, typeDef);
|
||||
}
|
||||
|
||||
async function createUsersTable(query: { context: any }) {
|
||||
await query.context.createTable($db.tableName('users'), {
|
||||
id: {
|
||||
type: DataTypes.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true
|
||||
},
|
||||
username: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
unique: true
|
||||
},
|
||||
email: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
unique: true
|
||||
},
|
||||
password: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false
|
||||
},
|
||||
firstName: {
|
||||
type: DataTypes.STRING,
|
||||
},
|
||||
lastName: {
|
||||
type: DataTypes.STRING,
|
||||
},
|
||||
createdAt: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: () => new Date(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async function createRolesTable(query: { context: any }) {
|
||||
await query.context.createTable($db.tableName('roles'), {
|
||||
id: {
|
||||
type: DataTypes.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true
|
||||
},
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
unique: true
|
||||
},
|
||||
createdAt: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: () => new Date(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async function createUsersRolesTable(query: { context: any }) {
|
||||
await query.context.createTable($db.tableName('users_roles'), {
|
||||
id: {
|
||||
type: DataTypes.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true
|
||||
},
|
||||
userId: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
references: {
|
||||
model: $db.tableName('users'),
|
||||
key: 'id'
|
||||
}
|
||||
},
|
||||
roleId: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
references: {
|
||||
model: $db.tableName('roles'),
|
||||
key: 'id'
|
||||
}
|
||||
},
|
||||
createdAt: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: () => new Date(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async function createUserSessionsTable(query: { context: any }) {
|
||||
await query.context.createTable($db.tableName('user_sessions'), {
|
||||
id: {
|
||||
type: DataTypes.UUID,
|
||||
primaryKey: true,
|
||||
allowNull: false,
|
||||
defaultValue: () => uuidv4(),
|
||||
},
|
||||
userId: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
references: {
|
||||
model: $db.tableName('users'),
|
||||
key: 'id'
|
||||
}
|
||||
},
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true,
|
||||
},
|
||||
expiresAt: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: true,
|
||||
},
|
||||
createdAt: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: () => new Date(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async function createUserDevicesTable(query: { context: any }) {
|
||||
await query.context.createTable($db.tableName('user_devices'), {
|
||||
id: {
|
||||
type: DataTypes.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true
|
||||
},
|
||||
userId: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
references: {
|
||||
model: $db.tableName('users'),
|
||||
key: 'id'
|
||||
}
|
||||
},
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
createdAt: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: () => new Date(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async function up(query: { context: any }) {
|
||||
await createRolesTable({ context: query.context });
|
||||
await createUsersTable({ context: query.context });
|
||||
await createUserDevicesTable({ context: query.context });
|
||||
await createUsersRolesTable({ context: query.context });
|
||||
await createUserSessionsTable({ context: query.context });
|
||||
await createLocationHistoryTable({ context: query.context });
|
||||
}
|
||||
|
||||
async function down(query: { context: any }) {
|
||||
await query.context.dropTable($db.tableName('users'));
|
||||
await query.context.dropTable($db.tableName('roles'));
|
||||
await query.context.dropTable($db.tableName('user_devices'));
|
||||
await query.context.dropTable($db.tableName('users_roles'));
|
||||
await query.context.dropTable($db.tableName('user_sessions'));
|
||||
|
||||
if ($db.locationUrl !== $db.url) {
|
||||
console.log('The location history table is stored on an external database, skipping deletion');
|
||||
return;
|
||||
}
|
||||
|
||||
await query.context.dropTable($db.locationTable);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
up,
|
||||
down
|
||||
}
|
|
@ -51,7 +51,7 @@ function GPSData(locationTableColumns: Record<string, string>): Record<string, a
|
|||
};
|
||||
}
|
||||
|
||||
const postalCodeCol: string = locationTableColumns['postal_code'];
|
||||
const postalCodeCol: string = locationTableColumns['postalCode'];
|
||||
if (postalCodeCol?.length) {
|
||||
typeDef[postalCodeCol] = {
|
||||
type: DataTypes.STRING,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { DataTypes, } from 'sequelize';
|
||||
import { DataTypes } from 'sequelize';
|
||||
|
||||
function User(): Record<string, any> {
|
||||
return {
|
||||
|
@ -34,12 +34,6 @@ function User(): Record<string, any> {
|
|||
allowNull: false,
|
||||
defaultValue: () => new Date(),
|
||||
},
|
||||
updatedAt: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: () => new Date(),
|
||||
onUpdate: () => new Date(),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
|
26
src/db/types/UserDevice.ts
Normal file
26
src/db/types/UserDevice.ts
Normal file
|
@ -0,0 +1,26 @@
|
|||
import { DataTypes, } from 'sequelize';
|
||||
|
||||
function UserDevice(): Record<string, any> {
|
||||
return {
|
||||
id: {
|
||||
type: DataTypes.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true
|
||||
},
|
||||
userId: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: false,
|
||||
},
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
createdAt: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: () => new Date(),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default UserDevice;
|
|
@ -20,12 +20,6 @@ function UserRole(): Record<string, any> {
|
|||
allowNull: false,
|
||||
defaultValue: () => new Date(),
|
||||
},
|
||||
updatedAt: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: () => new Date(),
|
||||
onUpdate: () => new Date(),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -22,12 +22,6 @@ function UserSession(): Record<string, any> {
|
|||
allowNull: false,
|
||||
defaultValue: () => new Date(),
|
||||
},
|
||||
updatedAt: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: false,
|
||||
defaultValue: () => new Date(),
|
||||
onUpdate: () => new Date(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@ class User {
|
|||
public firstName: Optional<string>;
|
||||
public lastName: Optional<string>;
|
||||
public createdAt: Optional<Date>;
|
||||
public updatedAt: Optional<Date>;
|
||||
|
||||
constructor({
|
||||
id,
|
||||
|
@ -23,7 +22,6 @@ class User {
|
|||
firstName = null,
|
||||
lastName = null,
|
||||
createdAt = null,
|
||||
updatedAt = null,
|
||||
}: User) {
|
||||
this.id = id;
|
||||
this.username = username;
|
||||
|
@ -32,7 +30,6 @@ class User {
|
|||
this.firstName = firstName;
|
||||
this.lastName = lastName;
|
||||
this.createdAt = createdAt;
|
||||
this.updatedAt = updatedAt;
|
||||
}
|
||||
|
||||
public static hashPassword(password: string): string {
|
||||
|
|
|
@ -7,22 +7,19 @@ class UserSession {
|
|||
public userId: number;
|
||||
public expiresAt: Optional<Date>;
|
||||
public createdAt: Optional<Date>;
|
||||
public updatedAt: Optional<Date>;
|
||||
|
||||
constructor({
|
||||
id,
|
||||
userId,
|
||||
expiresAt = null,
|
||||
createdAt = null,
|
||||
updatedAt = null,
|
||||
}: any) {
|
||||
this.id = id;
|
||||
this.userId = userId;
|
||||
this.expiresAt = expiresAt;
|
||||
this.createdAt = createdAt;
|
||||
this.updatedAt = updatedAt;
|
||||
|
||||
['expiresAt', 'createdAt', 'updatedAt'].forEach((key) => {
|
||||
['expiresAt', 'createdAt'].forEach((key) => {
|
||||
if ((this as any)[key] && !((this as any)[key] instanceof Date)) {
|
||||
(this as any)[key] = new Date((this as any)[key]);
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ class Location {
|
|||
address: data[mappings.address],
|
||||
locality: data[mappings.locality],
|
||||
country: data[mappings.country],
|
||||
postalCode: data[mappings.postal_code],
|
||||
postalCode: data[mappings.postalCode],
|
||||
timestamp: data[mappings.timestamp],
|
||||
});
|
||||
});
|
||||
|
|
|
@ -20,10 +20,14 @@ class UserSessions {
|
|||
return session;
|
||||
}
|
||||
|
||||
public async create(userId: number, expiresAt: Optional<Date> = null): Promise<UserSession> {
|
||||
public async create(userId: number, args: {
|
||||
expiresAt?: Optional<Date>,
|
||||
name?: Optional<string>,
|
||||
}): Promise<UserSession> {
|
||||
const session = await $db.UserSession().create({
|
||||
userId,
|
||||
expiresAt: expiresAt ? new Date(expiresAt).toISOString() : null,
|
||||
name: args.name,
|
||||
expiresAt: args.expiresAt ? new Date(args.expiresAt).toISOString() : null,
|
||||
});
|
||||
|
||||
return new UserSession(session.dataValues);
|
||||
|
|
|
@ -92,7 +92,7 @@ class LocationRequest {
|
|||
}
|
||||
|
||||
if (this.postalCode != null) {
|
||||
where[colMapping.postal_code || 'postal_code'] = this.postalCode;
|
||||
where[colMapping.postalCode || 'postalCode'] = this.postalCode;
|
||||
}
|
||||
|
||||
queryMap.where = where;
|
||||
|
|
|
@ -47,7 +47,11 @@ class Auth extends ApiV1Route {
|
|||
}
|
||||
}
|
||||
|
||||
session = await $repos.userSessions.create(user.id, expiresAtDate);
|
||||
session = await $repos.userSessions.create(user.id, {
|
||||
name: req.body?.name,
|
||||
expiresAt: expiresAtDate,
|
||||
})
|
||||
|
||||
setCookie(res, {
|
||||
name: 'session',
|
||||
value: session.getToken(),
|
||||
|
|
Loading…
Add table
Reference in a new issue