Add registration
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1 +1,4 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
|
.env
|
||||||
|
data/
|
||||||
|
dist/
|
||||||
@@ -30,6 +30,8 @@ services:
|
|||||||
labels:
|
labels:
|
||||||
- "traefik.http.routers.backend.rule=Host(`api.cashlow.local`)"
|
- "traefik.http.routers.backend.rule=Host(`api.cashlow.local`)"
|
||||||
- "traefik.http.services.backend.loadbalancer.server.port=3000"
|
- "traefik.http.services.backend.loadbalancer.server.port=3000"
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
|
||||||
frontend:
|
frontend:
|
||||||
tty: true
|
tty: true
|
||||||
@@ -46,6 +48,21 @@ services:
|
|||||||
- "traefik.http.routers.frontend.rule=Host(`app.cashlow.local`)"
|
- "traefik.http.routers.frontend.rule=Host(`app.cashlow.local`)"
|
||||||
- "traefik.http.services.frontend.loadbalancer.server.port=3000"
|
- "traefik.http.services.frontend.loadbalancer.server.port=3000"
|
||||||
|
|
||||||
|
database:
|
||||||
|
tty: true
|
||||||
|
restart: unless-stopped
|
||||||
|
image: timescale/timescaledb-ha:pg17
|
||||||
|
volumes:
|
||||||
|
- ./data/postgres:/home/postgres/pgdata/data
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
user: root
|
||||||
|
ports:
|
||||||
|
- "5432:5432"
|
||||||
|
networks:
|
||||||
|
cashlow:
|
||||||
|
ipv4_address: 10.231.215.4
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
cashlow:
|
cashlow:
|
||||||
driver: bridge
|
driver: bridge
|
||||||
|
|||||||
17
docs/yaak/yaak.ev_FHr7MPpAvE.yaml
Normal file
17
docs/yaak/yaak.ev_FHr7MPpAvE.yaml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
type: environment
|
||||||
|
model: environment
|
||||||
|
id: ev_FHr7MPpAvE
|
||||||
|
workspaceId: wk_yK68KSnsqe
|
||||||
|
createdAt: 2025-12-22T17:05:40.703553024
|
||||||
|
updatedAt: 2025-12-22T17:06:07.650085870
|
||||||
|
name: Global Variables
|
||||||
|
public: true
|
||||||
|
base: true
|
||||||
|
parentModel: workspace
|
||||||
|
parentId: null
|
||||||
|
variables:
|
||||||
|
- enabled: true
|
||||||
|
name: BASE_URL
|
||||||
|
value: http://api.cashlow.local
|
||||||
|
id: Zm8JuTSFX6
|
||||||
|
color: null
|
||||||
13
docs/yaak/yaak.fl_kD6z8aiTcL.yaml
Normal file
13
docs/yaak/yaak.fl_kD6z8aiTcL.yaml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
type: folder
|
||||||
|
model: folder
|
||||||
|
id: fl_kD6z8aiTcL
|
||||||
|
createdAt: 2025-12-22T21:56:20.134411915
|
||||||
|
updatedAt: 2025-12-22T21:56:20.134415476
|
||||||
|
workspaceId: wk_yK68KSnsqe
|
||||||
|
folderId: null
|
||||||
|
authentication: {}
|
||||||
|
authenticationType: null
|
||||||
|
description: ''
|
||||||
|
headers: []
|
||||||
|
name: /users
|
||||||
|
sortPriority: -1766440600000.0
|
||||||
28
docs/yaak/yaak.rq_hdQFMgWyrq.yaml
Normal file
28
docs/yaak/yaak.rq_hdQFMgWyrq.yaml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
type: http_request
|
||||||
|
model: http_request
|
||||||
|
id: rq_hdQFMgWyrq
|
||||||
|
createdAt: 2025-12-22T17:06:16.224935675
|
||||||
|
updatedAt: 2025-12-22T22:01:44.917855863
|
||||||
|
workspaceId: wk_yK68KSnsqe
|
||||||
|
folderId: fl_kD6z8aiTcL
|
||||||
|
authentication: {}
|
||||||
|
authenticationType: null
|
||||||
|
body:
|
||||||
|
text: |-
|
||||||
|
{
|
||||||
|
"username": "Martin Petr",
|
||||||
|
"email": "me2@martinpetr.dev",
|
||||||
|
"password": "Aa12345678!"
|
||||||
|
}
|
||||||
|
bodyType: application/json
|
||||||
|
description: ''
|
||||||
|
headers:
|
||||||
|
- enabled: true
|
||||||
|
name: Content-Type
|
||||||
|
value: application/json
|
||||||
|
id: GmRxir0VsD
|
||||||
|
method: POST
|
||||||
|
name: /users
|
||||||
|
sortPriority: 0.0
|
||||||
|
url: ${[ BASE_URL ]}/users
|
||||||
|
urlParameters: []
|
||||||
14
docs/yaak/yaak.wk_yK68KSnsqe.yaml
Normal file
14
docs/yaak/yaak.wk_yK68KSnsqe.yaml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
type: workspace
|
||||||
|
model: workspace
|
||||||
|
id: wk_yK68KSnsqe
|
||||||
|
createdAt: 2025-12-22T17:05:40.658814603
|
||||||
|
updatedAt: 2025-12-22T17:05:40.658816978
|
||||||
|
authentication: {}
|
||||||
|
authenticationType: null
|
||||||
|
description: ''
|
||||||
|
headers: []
|
||||||
|
name: Cashlow
|
||||||
|
encryptionKeyChallenge: null
|
||||||
|
settingValidateCertificates: true
|
||||||
|
settingFollowRedirects: true
|
||||||
|
settingRequestTimeout: 0
|
||||||
@@ -8,6 +8,9 @@
|
|||||||
"@nestjs/core": "^11.0.1",
|
"@nestjs/core": "^11.0.1",
|
||||||
"@nestjs/platform-express": "^11.0.1",
|
"@nestjs/platform-express": "^11.0.1",
|
||||||
"axios": "^1.13.2",
|
"axios": "^1.13.2",
|
||||||
|
"bcrypt": "^6.0.0",
|
||||||
|
"class-transformer": "^0.5.1",
|
||||||
|
"class-validator": "^0.14.3",
|
||||||
"pg": "^8.16.3",
|
"pg": "^8.16.3",
|
||||||
"reflect-metadata": "^0.2.2",
|
"reflect-metadata": "^0.2.2",
|
||||||
"rxjs": "^7.8.1",
|
"rxjs": "^7.8.1",
|
||||||
@@ -42,6 +45,7 @@
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
"trustedDependencies": [
|
"trustedDependencies": [
|
||||||
|
"bcrypt",
|
||||||
"unrs-resolver",
|
"unrs-resolver",
|
||||||
"@nestjs/core",
|
"@nestjs/core",
|
||||||
"@swc/core",
|
"@swc/core",
|
||||||
@@ -423,6 +427,8 @@
|
|||||||
|
|
||||||
"@types/supertest": ["@types/supertest@6.0.3", "", { "dependencies": { "@types/methods": "^1.1.4", "@types/superagent": "^8.1.0" } }, "sha512-8WzXq62EXFhJ7QsH3Ocb/iKQ/Ty9ZVWnVzoTKc9tyyFRRF3a74Tk2+TLFgaFFw364Ere+npzHKEJ6ga2LzIL7w=="],
|
"@types/supertest": ["@types/supertest@6.0.3", "", { "dependencies": { "@types/methods": "^1.1.4", "@types/superagent": "^8.1.0" } }, "sha512-8WzXq62EXFhJ7QsH3Ocb/iKQ/Ty9ZVWnVzoTKc9tyyFRRF3a74Tk2+TLFgaFFw364Ere+npzHKEJ6ga2LzIL7w=="],
|
||||||
|
|
||||||
|
"@types/validator": ["@types/validator@13.15.10", "", {}, "sha512-T8L6i7wCuyoK8A/ZeLYt1+q0ty3Zb9+qbSSvrIVitzT3YjZqkTZ40IbRsPanlB4h1QB3JVL1SYCdR6ngtFYcuA=="],
|
||||||
|
|
||||||
"@types/yargs": ["@types/yargs@17.0.35", "", { "dependencies": { "@types/yargs-parser": "*" } }, "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg=="],
|
"@types/yargs": ["@types/yargs@17.0.35", "", { "dependencies": { "@types/yargs-parser": "*" } }, "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg=="],
|
||||||
|
|
||||||
"@types/yargs-parser": ["@types/yargs-parser@21.0.3", "", {}, "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ=="],
|
"@types/yargs-parser": ["@types/yargs-parser@21.0.3", "", {}, "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ=="],
|
||||||
@@ -609,6 +615,8 @@
|
|||||||
|
|
||||||
"baseline-browser-mapping": ["baseline-browser-mapping@2.9.11", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ=="],
|
"baseline-browser-mapping": ["baseline-browser-mapping@2.9.11", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ=="],
|
||||||
|
|
||||||
|
"bcrypt": ["bcrypt@6.0.0", "", { "dependencies": { "node-addon-api": "^8.3.0", "node-gyp-build": "^4.8.4" } }, "sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg=="],
|
||||||
|
|
||||||
"bin-version": ["bin-version@6.0.0", "", { "dependencies": { "execa": "^5.0.0", "find-versions": "^5.0.0" } }, "sha512-nk5wEsP4RiKjG+vF+uG8lFsEn4d7Y6FVDamzzftSunXOoOcOOkzcWdKVlGgFFwlUQCj63SgnUkLLGF8v7lufhw=="],
|
"bin-version": ["bin-version@6.0.0", "", { "dependencies": { "execa": "^5.0.0", "find-versions": "^5.0.0" } }, "sha512-nk5wEsP4RiKjG+vF+uG8lFsEn4d7Y6FVDamzzftSunXOoOcOOkzcWdKVlGgFFwlUQCj63SgnUkLLGF8v7lufhw=="],
|
||||||
|
|
||||||
"bin-version-check": ["bin-version-check@5.1.0", "", { "dependencies": { "bin-version": "^6.0.0", "semver": "^7.5.3", "semver-truncate": "^3.0.0" } }, "sha512-bYsvMqJ8yNGILLz1KP9zKLzQ6YpljV3ln1gqhuLkUtyfGi3qXKGuK2p+U4NAvjVFzDFiBBtOpCOSFNuYYEGZ5g=="],
|
"bin-version-check": ["bin-version-check@5.1.0", "", { "dependencies": { "bin-version": "^6.0.0", "semver": "^7.5.3", "semver-truncate": "^3.0.0" } }, "sha512-bYsvMqJ8yNGILLz1KP9zKLzQ6YpljV3ln1gqhuLkUtyfGi3qXKGuK2p+U4NAvjVFzDFiBBtOpCOSFNuYYEGZ5g=="],
|
||||||
@@ -667,6 +675,10 @@
|
|||||||
|
|
||||||
"cjs-module-lexer": ["cjs-module-lexer@2.1.1", "", {}, "sha512-+CmxIZ/L2vNcEfvNtLdU0ZQ6mbq3FZnwAP2PPTiKP+1QOoKwlKlPgb8UKV0Dds7QVaMnHm+FwSft2VB0s/SLjQ=="],
|
"cjs-module-lexer": ["cjs-module-lexer@2.1.1", "", {}, "sha512-+CmxIZ/L2vNcEfvNtLdU0ZQ6mbq3FZnwAP2PPTiKP+1QOoKwlKlPgb8UKV0Dds7QVaMnHm+FwSft2VB0s/SLjQ=="],
|
||||||
|
|
||||||
|
"class-transformer": ["class-transformer@0.5.1", "", {}, "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw=="],
|
||||||
|
|
||||||
|
"class-validator": ["class-validator@0.14.3", "", { "dependencies": { "@types/validator": "^13.15.3", "libphonenumber-js": "^1.11.1", "validator": "^13.15.20" } }, "sha512-rXXekcjofVN1LTOSw+u4u9WXVEUvNBVjORW154q/IdmYWy1nMbOU9aNtZB0t8m+FJQ9q91jlr2f9CwwUFdFMRA=="],
|
||||||
|
|
||||||
"cli-cursor": ["cli-cursor@3.1.0", "", { "dependencies": { "restore-cursor": "^3.1.0" } }, "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw=="],
|
"cli-cursor": ["cli-cursor@3.1.0", "", { "dependencies": { "restore-cursor": "^3.1.0" } }, "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw=="],
|
||||||
|
|
||||||
"cli-spinners": ["cli-spinners@2.9.2", "", {}, "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg=="],
|
"cli-spinners": ["cli-spinners@2.9.2", "", {}, "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg=="],
|
||||||
@@ -1085,6 +1097,8 @@
|
|||||||
|
|
||||||
"levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="],
|
"levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="],
|
||||||
|
|
||||||
|
"libphonenumber-js": ["libphonenumber-js@1.12.33", "", {}, "sha512-r9kw4OA6oDO4dPXkOrXTkArQAafIKAU71hChInV4FxZ69dxCfbwQGDPzqR5/vea94wU705/3AZroEbSoeVWrQw=="],
|
||||||
|
|
||||||
"lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="],
|
"lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="],
|
||||||
|
|
||||||
"load-esm": ["load-esm@1.0.3", "", {}, "sha512-v5xlu8eHD1+6r8EHTg6hfmO97LN8ugKtiXcy5e6oN72iD2r6u0RPfLl6fxM+7Wnh2ZRq15o0russMst44WauPA=="],
|
"load-esm": ["load-esm@1.0.3", "", {}, "sha512-v5xlu8eHD1+6r8EHTg6hfmO97LN8ugKtiXcy5e6oN72iD2r6u0RPfLl6fxM+7Wnh2ZRq15o0russMst44WauPA=="],
|
||||||
@@ -1161,8 +1175,12 @@
|
|||||||
|
|
||||||
"node-abort-controller": ["node-abort-controller@3.1.1", "", {}, "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ=="],
|
"node-abort-controller": ["node-abort-controller@3.1.1", "", {}, "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ=="],
|
||||||
|
|
||||||
|
"node-addon-api": ["node-addon-api@8.5.0", "", {}, "sha512-/bRZty2mXUIFY/xU5HLvveNHlswNJej+RnxBjOMkidWfwZzgTbPG1E3K5TOxRLOR+5hX7bSofy8yf1hZevMS8A=="],
|
||||||
|
|
||||||
"node-emoji": ["node-emoji@1.11.0", "", { "dependencies": { "lodash": "^4.17.21" } }, "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A=="],
|
"node-emoji": ["node-emoji@1.11.0", "", { "dependencies": { "lodash": "^4.17.21" } }, "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A=="],
|
||||||
|
|
||||||
|
"node-gyp-build": ["node-gyp-build@4.8.4", "", { "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", "node-gyp-build-test": "build-test.js" } }, "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ=="],
|
||||||
|
|
||||||
"node-int64": ["node-int64@0.4.0", "", {}, "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw=="],
|
"node-int64": ["node-int64@0.4.0", "", {}, "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw=="],
|
||||||
|
|
||||||
"node-releases": ["node-releases@2.0.27", "", {}, "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA=="],
|
"node-releases": ["node-releases@2.0.27", "", {}, "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA=="],
|
||||||
@@ -1489,6 +1507,8 @@
|
|||||||
|
|
||||||
"v8-to-istanbul": ["v8-to-istanbul@9.3.0", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", "convert-source-map": "^2.0.0" } }, "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA=="],
|
"v8-to-istanbul": ["v8-to-istanbul@9.3.0", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", "convert-source-map": "^2.0.0" } }, "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA=="],
|
||||||
|
|
||||||
|
"validator": ["validator@13.15.26", "", {}, "sha512-spH26xU080ydGggxRyR1Yhcbgx+j3y5jbNXk/8L+iRvdIEQ4uTRH2Sgf2dokud6Q4oAtsbNvJ1Ft+9xmm6IZcA=="],
|
||||||
|
|
||||||
"vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="],
|
"vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="],
|
||||||
|
|
||||||
"walker": ["walker@1.0.8", "", { "dependencies": { "makeerror": "1.0.12" } }, "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ=="],
|
"walker": ["walker@1.0.8", "", { "dependencies": { "makeerror": "1.0.12" } }, "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ=="],
|
||||||
|
|||||||
44
packages/backend/dist/app.controller.js
vendored
44
packages/backend/dist/app.controller.js
vendored
@@ -1,44 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", {
|
|
||||||
value: true
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "AppController", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function() {
|
|
||||||
return AppController;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const _common = require("@nestjs/common");
|
|
||||||
const _appservice = require("./app.service");
|
|
||||||
function _ts_decorate(decorators, target, key, desc) {
|
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
||||||
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
||||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
||||||
}
|
|
||||||
function _ts_metadata(k, v) {
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
||||||
}
|
|
||||||
let AppController = class AppController {
|
|
||||||
getHello() {
|
|
||||||
return this.appService.getHello();
|
|
||||||
}
|
|
||||||
constructor(appService){
|
|
||||||
this.appService = appService;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
_ts_decorate([
|
|
||||||
(0, _common.Get)(),
|
|
||||||
_ts_metadata("design:type", Function),
|
|
||||||
_ts_metadata("design:paramtypes", []),
|
|
||||||
_ts_metadata("design:returntype", String)
|
|
||||||
], AppController.prototype, "getHello", null);
|
|
||||||
AppController = _ts_decorate([
|
|
||||||
(0, _common.Controller)(),
|
|
||||||
_ts_metadata("design:type", Function),
|
|
||||||
_ts_metadata("design:paramtypes", [
|
|
||||||
typeof _appservice.AppService === "undefined" ? Object : _appservice.AppService
|
|
||||||
])
|
|
||||||
], AppController);
|
|
||||||
|
|
||||||
//# sourceMappingURL=app.controller.js.map
|
|
||||||
1
packages/backend/dist/app.controller.js.map
vendored
1
packages/backend/dist/app.controller.js.map
vendored
@@ -1 +0,0 @@
|
|||||||
{"version":3,"sources":["../src/app.controller.ts"],"sourcesContent":["import { Controller, Get } from '@nestjs/common';\nimport { AppService } from './app.service';\n\n@Controller()\nexport class AppController {\n constructor(private readonly appService: AppService) {}\n\n @Get()\n getHello(): string {\n return this.appService.getHello();\n }\n}\n"],"names":["AppController","getHello","appService"],"mappings":";;;;+BAIaA;;;eAAAA;;;wBAJmB;4BACL;;;;;;;;;;AAGpB,IAAA,AAAMA,gBAAN,MAAMA;IAIXC,WAAmB;QACjB,OAAO,IAAI,CAACC,UAAU,CAACD,QAAQ;IACjC;IALA,YAAY,AAAiBC,UAAsB,CAAE;aAAxBA,aAAAA;IAAyB;AAMxD"}
|
|
||||||
28
packages/backend/dist/app.controller.spec.js
vendored
28
packages/backend/dist/app.controller.spec.js
vendored
@@ -1,28 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", {
|
|
||||||
value: true
|
|
||||||
});
|
|
||||||
const _testing = require("@nestjs/testing");
|
|
||||||
const _appcontroller = require("./app.controller");
|
|
||||||
const _appservice = require("./app.service");
|
|
||||||
describe('AppController', ()=>{
|
|
||||||
let appController;
|
|
||||||
beforeEach(async ()=>{
|
|
||||||
const app = await _testing.Test.createTestingModule({
|
|
||||||
controllers: [
|
|
||||||
_appcontroller.AppController
|
|
||||||
],
|
|
||||||
providers: [
|
|
||||||
_appservice.AppService
|
|
||||||
]
|
|
||||||
}).compile();
|
|
||||||
appController = app.get(_appcontroller.AppController);
|
|
||||||
});
|
|
||||||
describe('root', ()=>{
|
|
||||||
it('should return "Hello World!"', ()=>{
|
|
||||||
expect(appController.getHello()).toBe('Hello World!');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
//# sourceMappingURL=app.controller.spec.js.map
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{"version":3,"sources":["../src/app.controller.spec.ts"],"sourcesContent":["import { Test, TestingModule } from '@nestjs/testing';\nimport { AppController } from './app.controller';\nimport { AppService } from './app.service';\n\ndescribe('AppController', () => {\n let appController: AppController;\n\n beforeEach(async () => {\n const app: TestingModule = await Test.createTestingModule({\n controllers: [AppController],\n providers: [AppService],\n }).compile();\n\n appController = app.get<AppController>(AppController);\n });\n\n describe('root', () => {\n it('should return \"Hello World!\"', () => {\n expect(appController.getHello()).toBe('Hello World!');\n });\n });\n});\n"],"names":["describe","appController","beforeEach","app","Test","createTestingModule","controllers","AppController","providers","AppService","compile","get","it","expect","getHello","toBe"],"mappings":";;;;yBAAoC;+BACN;4BACH;AAE3BA,SAAS,iBAAiB;IACxB,IAAIC;IAEJC,WAAW;QACT,MAAMC,MAAqB,MAAMC,aAAI,CAACC,mBAAmB,CAAC;YACxDC,aAAa;gBAACC,4BAAa;aAAC;YAC5BC,WAAW;gBAACC,sBAAU;aAAC;QACzB,GAAGC,OAAO;QAEVT,gBAAgBE,IAAIQ,GAAG,CAAgBJ,4BAAa;IACtD;IAEAP,SAAS,QAAQ;QACfY,GAAG,gCAAgC;YACjCC,OAAOZ,cAAca,QAAQ,IAAIC,IAAI,CAAC;QACxC;IACF;AACF"}
|
|
||||||
11
packages/backend/dist/app.module.js
vendored
11
packages/backend/dist/app.module.js
vendored
@@ -9,8 +9,10 @@ Object.defineProperty(exports, "AppModule", {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
const _common = require("@nestjs/common");
|
const _common = require("@nestjs/common");
|
||||||
const _appcontroller = require("./app.controller");
|
const _appcontroller = require("./routes/app.controller");
|
||||||
const _appservice = require("./app.service");
|
const _appservice = require("./routes/app.service");
|
||||||
|
const _financemodule = require("./routes/finance/finance.module");
|
||||||
|
const _usersmodule = require("./routes/users/users.module");
|
||||||
function _ts_decorate(decorators, target, key, desc) {
|
function _ts_decorate(decorators, target, key, desc) {
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||||
@@ -21,7 +23,10 @@ let AppModule = class AppModule {
|
|||||||
};
|
};
|
||||||
AppModule = _ts_decorate([
|
AppModule = _ts_decorate([
|
||||||
(0, _common.Module)({
|
(0, _common.Module)({
|
||||||
imports: [],
|
imports: [
|
||||||
|
_usersmodule.UsersModule,
|
||||||
|
_financemodule.FinanceModule
|
||||||
|
],
|
||||||
controllers: [
|
controllers: [
|
||||||
_appcontroller.AppController
|
_appcontroller.AppController
|
||||||
],
|
],
|
||||||
|
|||||||
2
packages/backend/dist/app.module.js.map
vendored
2
packages/backend/dist/app.module.js.map
vendored
@@ -1 +1 @@
|
|||||||
{"version":3,"sources":["../src/app.module.ts"],"sourcesContent":["import { Module } from '@nestjs/common';\nimport { AppController } from './app.controller';\nimport { AppService } from './app.service';\n\n@Module({\n imports: [],\n controllers: [AppController],\n providers: [AppService],\n})\nexport class AppModule {}\n"],"names":["AppModule","imports","controllers","AppController","providers","AppService"],"mappings":";;;;+BASaA;;;eAAAA;;;wBATU;+BACO;4BACH;;;;;;;AAOpB,IAAA,AAAMA,YAAN,MAAMA;AAAW;;;QAJtBC,SAAS,EAAE;QACXC,aAAa;YAACC,4BAAa;SAAC;QAC5BC,WAAW;YAACC,sBAAU;SAAC"}
|
{"version":3,"sources":["../src/app.module.ts"],"sourcesContent":["import { Module } from '@nestjs/common';\nimport { AppController } from './routes/app.controller';\nimport { AppService } from './routes/app.service';\nimport { FinanceModule } from './routes/finance/finance.module';\nimport { UsersModule } from './routes/users/users.module';\n\n@Module({\n imports: [UsersModule, FinanceModule],\n controllers: [AppController],\n providers: [AppService],\n})\nexport class AppModule {}\n"],"names":["AppModule","imports","UsersModule","FinanceModule","controllers","AppController","providers","AppService"],"mappings":";;;;+BAWaA;;;eAAAA;;;wBAXU;+BACO;4BACH;+BACG;6BACF;;;;;;;AAOrB,IAAA,AAAMA,YAAN,MAAMA;AAAW;;;QAJtBC,SAAS;YAACC,wBAAW;YAAEC,4BAAa;SAAC;QACrCC,aAAa;YAACC,4BAAa;SAAC;QAC5BC,WAAW;YAACC,sBAAU;SAAC"}
|
||||||
27
packages/backend/dist/app.service.js
vendored
27
packages/backend/dist/app.service.js
vendored
@@ -1,27 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", {
|
|
||||||
value: true
|
|
||||||
});
|
|
||||||
Object.defineProperty(exports, "AppService", {
|
|
||||||
enumerable: true,
|
|
||||||
get: function() {
|
|
||||||
return AppService;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const _common = require("@nestjs/common");
|
|
||||||
function _ts_decorate(decorators, target, key, desc) {
|
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
||||||
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
||||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
||||||
}
|
|
||||||
let AppService = class AppService {
|
|
||||||
getHello() {
|
|
||||||
return 'Hello World!';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
AppService = _ts_decorate([
|
|
||||||
(0, _common.Injectable)()
|
|
||||||
], AppService);
|
|
||||||
|
|
||||||
//# sourceMappingURL=app.service.js.map
|
|
||||||
1
packages/backend/dist/app.service.js.map
vendored
1
packages/backend/dist/app.service.js.map
vendored
@@ -1 +0,0 @@
|
|||||||
{"version":3,"sources":["../src/app.service.ts"],"sourcesContent":["import { Injectable } from '@nestjs/common';\n\n@Injectable()\nexport class AppService {\n getHello(): string {\n return 'Hello World!';\n }\n}\n"],"names":["AppService","getHello"],"mappings":";;;;+BAGaA;;;eAAAA;;;wBAHc;;;;;;;AAGpB,IAAA,AAAMA,aAAN,MAAMA;IACXC,WAAmB;QACjB,OAAO;IACT;AACF"}
|
|
||||||
4
packages/backend/dist/main.js
vendored
4
packages/backend/dist/main.js
vendored
@@ -4,8 +4,12 @@ Object.defineProperty(exports, "__esModule", {
|
|||||||
});
|
});
|
||||||
const _core = require("@nestjs/core");
|
const _core = require("@nestjs/core");
|
||||||
const _appmodule = require("./app.module");
|
const _appmodule = require("./app.module");
|
||||||
|
const _Database = require("./classes/database/Database");
|
||||||
|
const _common = require("@nestjs/common");
|
||||||
async function bootstrap() {
|
async function bootstrap() {
|
||||||
const app = await _core.NestFactory.create(_appmodule.AppModule);
|
const app = await _core.NestFactory.create(_appmodule.AppModule);
|
||||||
|
app.useGlobalPipes(new _common.ValidationPipe());
|
||||||
|
await _Database.Database.initialize();
|
||||||
await app.listen(process.env.PORT ?? 3000);
|
await app.listen(process.env.PORT ?? 3000);
|
||||||
}
|
}
|
||||||
bootstrap();
|
bootstrap();
|
||||||
|
|||||||
2
packages/backend/dist/main.js.map
vendored
2
packages/backend/dist/main.js.map
vendored
@@ -1 +1 @@
|
|||||||
{"version":3,"sources":["../src/main.ts"],"sourcesContent":["import { NestFactory } from '@nestjs/core';\nimport { AppModule } from './app.module';\n\nasync function bootstrap() {\n const app = await NestFactory.create(AppModule);\n await app.listen(process.env.PORT ?? 3000);\n}\nbootstrap();\n"],"names":["bootstrap","app","NestFactory","create","AppModule","listen","process","env","PORT"],"mappings":";;;;sBAA4B;2BACF;AAE1B,eAAeA;IACb,MAAMC,MAAM,MAAMC,iBAAW,CAACC,MAAM,CAACC,oBAAS;IAC9C,MAAMH,IAAII,MAAM,CAACC,QAAQC,GAAG,CAACC,IAAI,IAAI;AACvC;AACAR"}
|
{"version":3,"sources":["../src/main.ts"],"sourcesContent":["import { NestFactory } from '@nestjs/core';\nimport { AppModule } from './app.module';\nimport { Database } from './classes/database/Database';\nimport { ValidationPipe } from '@nestjs/common';\n\nasync function bootstrap() {\n const app = await NestFactory.create(AppModule);\n\n app.useGlobalPipes(new ValidationPipe());\n\n await Database.initialize();\n\n await app.listen(process.env.PORT ?? 3000);\n}\nbootstrap();\n"],"names":["bootstrap","app","NestFactory","create","AppModule","useGlobalPipes","ValidationPipe","Database","initialize","listen","process","env","PORT"],"mappings":";;;;sBAA4B;2BACF;0BACD;wBACM;AAE/B,eAAeA;IACb,MAAMC,MAAM,MAAMC,iBAAW,CAACC,MAAM,CAACC,oBAAS;IAE9CH,IAAII,cAAc,CAAC,IAAIC,sBAAc;IAErC,MAAMC,kBAAQ,CAACC,UAAU;IAEzB,MAAMP,IAAIQ,MAAM,CAACC,QAAQC,GAAG,CAACC,IAAI,IAAI;AACvC;AACAZ"}
|
||||||
@@ -24,6 +24,9 @@
|
|||||||
"@nestjs/core": "^11.0.1",
|
"@nestjs/core": "^11.0.1",
|
||||||
"@nestjs/platform-express": "^11.0.1",
|
"@nestjs/platform-express": "^11.0.1",
|
||||||
"axios": "^1.13.2",
|
"axios": "^1.13.2",
|
||||||
|
"bcrypt": "^6.0.0",
|
||||||
|
"class-transformer": "^0.5.1",
|
||||||
|
"class-validator": "^0.14.3",
|
||||||
"pg": "^8.16.3",
|
"pg": "^8.16.3",
|
||||||
"reflect-metadata": "^0.2.2",
|
"reflect-metadata": "^0.2.2",
|
||||||
"rxjs": "^7.8.1",
|
"rxjs": "^7.8.1",
|
||||||
@@ -75,6 +78,7 @@
|
|||||||
"trustedDependencies": [
|
"trustedDependencies": [
|
||||||
"@nestjs/core",
|
"@nestjs/core",
|
||||||
"@swc/core",
|
"@swc/core",
|
||||||
|
"bcrypt",
|
||||||
"unrs-resolver"
|
"unrs-resolver"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { AppController } from './app.controller';
|
import { AppController } from './routes/app.controller';
|
||||||
import { AppService } from './app.service';
|
import { AppService } from './routes/app.service';
|
||||||
|
import { FinanceModule } from './routes/finance/finance.module';
|
||||||
|
import { UsersModule } from './routes/users/users.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [],
|
imports: [UsersModule, FinanceModule],
|
||||||
controllers: [AppController],
|
controllers: [AppController],
|
||||||
providers: [AppService],
|
providers: [AppService],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class AppService {
|
|
||||||
getHello(): string {
|
|
||||||
return 'Hello World!';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
43
packages/backend/src/classes/auth/AuthManager.ts
Normal file
43
packages/backend/src/classes/auth/AuthManager.ts
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import { BadRequestException } from '@nestjs/common';
|
||||||
|
import { Database } from '../database/Database';
|
||||||
|
import { UserDbEntity } from '../database/entities/User.entity';
|
||||||
|
import { PasswordHasher } from '../cryptography/PasswordHasher';
|
||||||
|
import { HashGenerator } from '../cryptography/HashGenerator';
|
||||||
|
import { randomUUID } from 'crypto';
|
||||||
|
|
||||||
|
export class AuthManager {
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
static async createUserAccount(
|
||||||
|
email: string,
|
||||||
|
password: string,
|
||||||
|
username: string,
|
||||||
|
) {
|
||||||
|
const existingUser = await this.#getUserByEmail(email);
|
||||||
|
if (existingUser) return new BadRequestException('User already exists');
|
||||||
|
|
||||||
|
const passwordHash = await PasswordHasher.hash(password);
|
||||||
|
const userHash = HashGenerator.generate(64);
|
||||||
|
|
||||||
|
const user = new UserDbEntity();
|
||||||
|
user.id = randomUUID();
|
||||||
|
user.email = email;
|
||||||
|
user.password = passwordHash;
|
||||||
|
user.username = username;
|
||||||
|
user.hash = userHash;
|
||||||
|
|
||||||
|
await Database.repositories.users.save(user);
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: user.id,
|
||||||
|
email: user.email,
|
||||||
|
username: user.username,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static async #getUserByEmail(email: string): Promise<UserDbEntity | null> {
|
||||||
|
if (!email || typeof email != 'string') return null;
|
||||||
|
|
||||||
|
return await Database.repositories.users.findOneBy({ email });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { randomBytes } from 'crypto';
|
||||||
|
|
||||||
|
export class HashGenerator {
|
||||||
|
static generate(length: number) {
|
||||||
|
return randomBytes(length / 2).toString('hex');
|
||||||
|
}
|
||||||
|
}
|
||||||
16
packages/backend/src/classes/cryptography/PasswordHasher.ts
Normal file
16
packages/backend/src/classes/cryptography/PasswordHasher.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import * as bc from 'bcrypt';
|
||||||
|
import { AUTH_PASSWORD_HASHING_ROUNDS } from 'src/config';
|
||||||
|
|
||||||
|
export class PasswordHasher {
|
||||||
|
static async hash(password: string): Promise<string> {
|
||||||
|
return await new Promise((r) =>
|
||||||
|
bc.hash(password, AUTH_PASSWORD_HASHING_ROUNDS, (e, hash) => r(hash)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static async compare(password: string, hash: string): Promise<boolean> {
|
||||||
|
return await new Promise((r) =>
|
||||||
|
bc.compare(password, hash, (e, res) => r(res)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
60
packages/backend/src/classes/database/Database.ts
Normal file
60
packages/backend/src/classes/database/Database.ts
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
import { DB_DATABASE, DB_HOST, DB_PASSWORD, DB_USERNAME } from 'src/config';
|
||||||
|
import { DataSource, Repository } from 'typeorm';
|
||||||
|
import { UserDbEntity } from './entities/User.entity';
|
||||||
|
import { BankAccountDbEntity } from './entities/BankAccount.entity';
|
||||||
|
|
||||||
|
const ENTITIES = {
|
||||||
|
users: UserDbEntity,
|
||||||
|
bankAccounts: BankAccountDbEntity,
|
||||||
|
};
|
||||||
|
|
||||||
|
export class Database {
|
||||||
|
static instance: Database = new Database();
|
||||||
|
|
||||||
|
#dataSource: DataSource;
|
||||||
|
|
||||||
|
#dbType: 'postgres' = 'postgres';
|
||||||
|
#dbHost = DB_HOST;
|
||||||
|
#dbPort = 5432;
|
||||||
|
#dbUsername = DB_USERNAME;
|
||||||
|
#dbPassword = DB_PASSWORD;
|
||||||
|
#dbDatabase = DB_DATABASE;
|
||||||
|
|
||||||
|
#entities = Object.values(ENTITIES);
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.#dataSource = new DataSource({
|
||||||
|
type: this.#dbType,
|
||||||
|
host: this.#dbHost,
|
||||||
|
port: this.#dbPort,
|
||||||
|
username: this.#dbUsername,
|
||||||
|
password: this.#dbPassword,
|
||||||
|
database: this.#dbDatabase,
|
||||||
|
synchronize: true,
|
||||||
|
entities: this.#entities,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
get repositories() {
|
||||||
|
return {
|
||||||
|
users: this.#dataSource.getRepository(UserDbEntity),
|
||||||
|
bankAccounts: this.#dataSource.getRepository(BankAccountDbEntity),
|
||||||
|
} as {
|
||||||
|
[K in keyof typeof ENTITIES]: Repository<
|
||||||
|
InstanceType<(typeof ENTITIES)[K]>
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static get repositories() {
|
||||||
|
return this.instance.repositories;
|
||||||
|
}
|
||||||
|
|
||||||
|
async initialize() {
|
||||||
|
await this.#dataSource.initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
static async initialize() {
|
||||||
|
await this.instance.initialize();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import {
|
||||||
|
Column,
|
||||||
|
Entity,
|
||||||
|
ManyToOne,
|
||||||
|
PrimaryColumn,
|
||||||
|
type Relation,
|
||||||
|
} from 'typeorm';
|
||||||
|
import { UserDbEntity } from './User.entity';
|
||||||
|
|
||||||
|
@Entity('bank_account')
|
||||||
|
export class BankAccountDbEntity {
|
||||||
|
@PrimaryColumn({
|
||||||
|
type: 'varchar',
|
||||||
|
length: 35,
|
||||||
|
})
|
||||||
|
id: string;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: 'varchar',
|
||||||
|
length: 100,
|
||||||
|
})
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => UserDbEntity, (user) => user.bankAccounts)
|
||||||
|
user: Relation<UserDbEntity>;
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import {
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
Entity,
|
||||||
|
ManyToMany,
|
||||||
|
OneToMany,
|
||||||
|
PrimaryColumn,
|
||||||
|
Relation,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
import { BankAccountDbEntity } from './BankAccount.entity';
|
||||||
|
|
||||||
|
@Entity('user')
|
||||||
|
export class UserDbEntity {
|
||||||
|
@PrimaryColumn({
|
||||||
|
type: 'varchar',
|
||||||
|
length: 36,
|
||||||
|
})
|
||||||
|
id: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
email: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
password: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
username: string;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: 'varchar',
|
||||||
|
length: 64,
|
||||||
|
})
|
||||||
|
hash: string;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt: Date;
|
||||||
|
|
||||||
|
@OneToMany(() => BankAccountDbEntity, (bankAccount) => bankAccount.user)
|
||||||
|
bankAccounts: Relation<BankAccountDbEntity>[];
|
||||||
|
}
|
||||||
6
packages/backend/src/config.ts
Normal file
6
packages/backend/src/config.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export const DB_HOST = process.env.IP_DATABASE;
|
||||||
|
export const DB_USERNAME = process.env.POSTGRES_USER;
|
||||||
|
export const DB_PASSWORD = process.env.POSTGRES_PASSWORD;
|
||||||
|
export const DB_DATABASE = process.env.POSTGRES_DB;
|
||||||
|
|
||||||
|
export const AUTH_PASSWORD_HASHING_ROUNDS = 14;
|
||||||
23
packages/backend/src/dto/CreateUserAccount.dto.ts
Normal file
23
packages/backend/src/dto/CreateUserAccount.dto.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import {
|
||||||
|
IsEmail,
|
||||||
|
IsString,
|
||||||
|
IsStrongPassword,
|
||||||
|
Length,
|
||||||
|
MaxLength,
|
||||||
|
MinLength,
|
||||||
|
} from 'class-validator';
|
||||||
|
|
||||||
|
export class CreateUserAccountDto {
|
||||||
|
@IsString()
|
||||||
|
@IsEmail()
|
||||||
|
email: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsStrongPassword()
|
||||||
|
@MaxLength(64)
|
||||||
|
password: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@Length(3, 64)
|
||||||
|
username: string;
|
||||||
|
}
|
||||||
@@ -1,8 +1,15 @@
|
|||||||
import { NestFactory } from '@nestjs/core';
|
import { NestFactory } from '@nestjs/core';
|
||||||
import { AppModule } from './app.module';
|
import { AppModule } from './app.module';
|
||||||
|
import { Database } from './classes/database/Database';
|
||||||
|
import { ValidationPipe } from '@nestjs/common';
|
||||||
|
|
||||||
async function bootstrap() {
|
async function bootstrap() {
|
||||||
const app = await NestFactory.create(AppModule);
|
const app = await NestFactory.create(AppModule);
|
||||||
|
|
||||||
|
app.useGlobalPipes(new ValidationPipe());
|
||||||
|
|
||||||
|
await Database.initialize();
|
||||||
|
|
||||||
await app.listen(process.env.PORT ?? 3000);
|
await app.listen(process.env.PORT ?? 3000);
|
||||||
}
|
}
|
||||||
bootstrap();
|
bootstrap();
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ describe('AppController', () => {
|
|||||||
appController = app.get<AppController>(AppController);
|
appController = app.get<AppController>(AppController);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('root', () => {
|
// describe('root', () => {
|
||||||
it('should return "Hello World!"', () => {
|
// it('should return "Hello World!"', () => {
|
||||||
expect(appController.getHello()).toBe('Hello World!');
|
// expect(appController.getHello()).toBe('Hello World!');
|
||||||
});
|
// });
|
||||||
});
|
// });
|
||||||
});
|
});
|
||||||
@@ -4,9 +4,4 @@ import { AppService } from './app.service';
|
|||||||
@Controller()
|
@Controller()
|
||||||
export class AppController {
|
export class AppController {
|
||||||
constructor(private readonly appService: AppService) {}
|
constructor(private readonly appService: AppService) {}
|
||||||
|
|
||||||
@Get()
|
|
||||||
getHello(): string {
|
|
||||||
return this.appService.getHello();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
4
packages/backend/src/routes/app.service.ts
Normal file
4
packages/backend/src/routes/app.service.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AppService {}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { Controller } from '@nestjs/common';
|
||||||
|
import { AccountService } from './account.service';
|
||||||
|
|
||||||
|
@Controller('/finance/account')
|
||||||
|
export class AccountController {
|
||||||
|
constructor(private readonly accountService: AccountService) {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { AccountController } from './account.controller';
|
||||||
|
import { AccountService } from './account.service';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [],
|
||||||
|
controllers: [AccountController],
|
||||||
|
providers: [AccountService],
|
||||||
|
})
|
||||||
|
export class AccountModule {}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AccountService {}
|
||||||
9
packages/backend/src/routes/finance/finance.module.ts
Normal file
9
packages/backend/src/routes/finance/finance.module.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { AccountModule } from './account/account.module';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [AccountModule],
|
||||||
|
controllers: [],
|
||||||
|
providers: [],
|
||||||
|
})
|
||||||
|
export class FinanceModule {}
|
||||||
15
packages/backend/src/routes/users/users.controller.ts
Normal file
15
packages/backend/src/routes/users/users.controller.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { Body, Controller, Post } from '@nestjs/common';
|
||||||
|
import { UsersService } from './users.service';
|
||||||
|
import { CreateUserAccountDto } from 'src/dto/CreateUserAccount.dto';
|
||||||
|
|
||||||
|
@Controller('/users')
|
||||||
|
export class UsersController {
|
||||||
|
constructor(private readonly usersService: UsersService) {}
|
||||||
|
|
||||||
|
@Post('/')
|
||||||
|
async createUserAccount(
|
||||||
|
@Body() { email, password, username }: CreateUserAccountDto,
|
||||||
|
) {
|
||||||
|
return await this.usersService.createUserAccount(email, password, username);
|
||||||
|
}
|
||||||
|
}
|
||||||
10
packages/backend/src/routes/users/users.module.ts
Normal file
10
packages/backend/src/routes/users/users.module.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { UsersController } from './users.controller';
|
||||||
|
import { UsersService } from './users.service';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [],
|
||||||
|
controllers: [UsersController],
|
||||||
|
providers: [UsersService],
|
||||||
|
})
|
||||||
|
export class UsersModule {}
|
||||||
9
packages/backend/src/routes/users/users.service.ts
Normal file
9
packages/backend/src/routes/users/users.service.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { AuthManager } from 'src/classes/auth/AuthManager';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class UsersService {
|
||||||
|
async createUserAccount(email: string, password: string, username: string) {
|
||||||
|
return await AuthManager.createUserAccount(email, password, username);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user