Compare commits
41 Commits
Author | SHA1 | Date | |
---|---|---|---|
6b22ec18a2 | |||
4e3dfdab49 | |||
d1011d0537 | |||
63dcaa4d7a | |||
3aff5cb712 | |||
1f4f290522 | |||
1544973e7b | |||
7a95e50ac3 | |||
a794ee636f | |||
0fafffd509 | |||
e2a29f4b65 | |||
aeeeec6e21 | |||
30655dc5a8 | |||
af4b235a51 | |||
5d8837809a | |||
cf01392e65 | |||
6f5a9771f0 | |||
91fc7f04ef | |||
74ccd6738b | |||
3922ca678d | |||
83f8e345fe | |||
1331a59414 | |||
c7af79da4b | |||
6abe4f67cb | |||
3211024750 | |||
076bd4e61b | |||
9d40b79426 | |||
465dcc3fae | |||
cfe166c85a | |||
77ce0752c1 | |||
82dcfd163c | |||
e6af154d0a | |||
a7c19cd750 | |||
0a40a6e2d1 | |||
28263bf4f9 | |||
63919836c4 | |||
ba29a321f0 | |||
13226e0fa9 | |||
cfcae77ad5 | |||
5ff927f236 | |||
2138819860 |
4
.gitignore
vendored
4
.gitignore
vendored
@ -5,7 +5,7 @@ build/
|
|||||||
!**/src/main/**/build/
|
!**/src/main/**/build/
|
||||||
!**/src/test/**/build/
|
!**/src/test/**/build/
|
||||||
node_modules
|
node_modules
|
||||||
|
*.db
|
||||||
### STS ###
|
### STS ###
|
||||||
.apt_generated
|
.apt_generated
|
||||||
.classpath
|
.classpath
|
||||||
@ -36,3 +36,5 @@ out/
|
|||||||
|
|
||||||
### VS Code ###
|
### VS Code ###
|
||||||
.vscode/
|
.vscode/
|
||||||
|
data.mv.db
|
||||||
|
data.trace.db
|
16
build.gradle
16
build.gradle
@ -12,9 +12,25 @@ repositories {
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jar {
|
||||||
|
enabled = false
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
|
||||||
|
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-web'
|
implementation 'org.springframework.boot:spring-boot-starter-web'
|
||||||
|
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||||
|
implementation 'com.h2database:h2:2.1.210'
|
||||||
|
implementation 'org.springframework.boot:spring-boot-starter-validation'
|
||||||
|
implementation group: 'org.springdoc', name: 'springdoc-openapi-ui', version: '1.6.5'
|
||||||
|
|
||||||
|
implementation 'org.springframework.boot:spring-boot-starter-security'
|
||||||
|
implementation 'com.auth0:java-jwt:4.4.0'
|
||||||
|
|
||||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||||
|
implementation 'org.hibernate.validator:hibernate-validator'
|
||||||
|
implementation 'org.springdoc:springdoc-openapi-ui:1.6.5'
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.named('test') {
|
tasks.named('test') {
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="ru">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<script src="node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
|
|
||||||
<link href="node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" />
|
|
||||||
<link href="node_modules/@fortawesome/fontawesome-free/css/all.min.css" rel="stylesheet" />
|
|
||||||
<title>Калькулятор</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<form class="mx-2 d-flex flex-column align-items-center text-center">
|
|
||||||
<div>
|
|
||||||
Первое число
|
|
||||||
<input id="first" class="form-control" type='number' value='0' />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
Операция
|
|
||||||
<select class="form-select" id="operation">
|
|
||||||
<option value="1">+</option>
|
|
||||||
<option value="2">-</option>
|
|
||||||
<option value="3">*</option>
|
|
||||||
<option value="4">/</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
Второе число
|
|
||||||
<input id="second" class="form-control" type='number' value='0' />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<button type="button" class="btn btn-primary" id="calculate">Тык</button>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
Результат:
|
|
||||||
<p id="result"> </p>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<script src="script.js"></script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
817
front/package-lock.json
generated
817
front/package-lock.json
generated
@ -1,817 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "int-prog",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"lockfileVersion": 2,
|
|
||||||
"requires": true,
|
|
||||||
"packages": {
|
|
||||||
"": {
|
|
||||||
"name": "int-prog",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"dependencies": {
|
|
||||||
"@fortawesome/fontawesome-free": "6.2.0",
|
|
||||||
"bootstrap": "5.2.1"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"http-server": "14.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@fortawesome/fontawesome-free": {
|
|
||||||
"version": "6.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.2.0.tgz",
|
|
||||||
"integrity": "sha512-CNR7qRIfCwWHNN7FnKUniva94edPdyQzil/zCwk3v6k4R6rR2Fr8i4s3PM7n/lyfPA6Zfko9z5WDzFxG9SW1uQ==",
|
|
||||||
"hasInstallScript": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@popperjs/core": {
|
|
||||||
"version": "2.11.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz",
|
|
||||||
"integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==",
|
|
||||||
"peer": true,
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/popperjs"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/ansi-styles": {
|
|
||||||
"version": "4.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
|
||||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"color-convert": "^2.0.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/async": {
|
|
||||||
"version": "2.6.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
|
|
||||||
"integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"lodash": "^4.17.14"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/basic-auth": {
|
|
||||||
"version": "2.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
|
|
||||||
"integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"safe-buffer": "5.1.2"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/bootstrap": {
|
|
||||||
"version": "5.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.1.tgz",
|
|
||||||
"integrity": "sha512-UQi3v2NpVPEi1n35dmRRzBJFlgvWHYwyem6yHhuT6afYF+sziEt46McRbT//kVXZ7b1YUYEVGdXEH74Nx3xzGA==",
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/twbs"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/bootstrap"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"peerDependencies": {
|
|
||||||
"@popperjs/core": "^2.11.6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"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==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"function-bind": "^1.1.1",
|
|
||||||
"get-intrinsic": "^1.0.2"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/chalk": {
|
|
||||||
"version": "4.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
|
||||||
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"ansi-styles": "^4.1.0",
|
|
||||||
"supports-color": "^7.1.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/color-convert": {
|
|
||||||
"version": "2.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
|
||||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"color-name": "~1.1.4"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=7.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/color-name": {
|
|
||||||
"version": "1.1.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
|
||||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/corser": {
|
|
||||||
"version": "2.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz",
|
|
||||||
"integrity": "sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/debug": {
|
|
||||||
"version": "3.2.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
|
|
||||||
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"ms": "^2.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/eventemitter3": {
|
|
||||||
"version": "4.0.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
|
|
||||||
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/follow-redirects": {
|
|
||||||
"version": "1.15.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
|
|
||||||
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
|
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"type": "individual",
|
|
||||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"debug": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/function-bind": {
|
|
||||||
"version": "1.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
|
||||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/get-intrinsic": {
|
|
||||||
"version": "1.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz",
|
|
||||||
"integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"function-bind": "^1.1.1",
|
|
||||||
"has": "^1.0.3",
|
|
||||||
"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==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"function-bind": "^1.1.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"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==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"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==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.4"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/he": {
|
|
||||||
"version": "1.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
|
|
||||||
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
|
|
||||||
"dev": true,
|
|
||||||
"bin": {
|
|
||||||
"he": "bin/he"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/html-encoding-sniffer": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"whatwg-encoding": "^2.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/http-proxy": {
|
|
||||||
"version": "1.18.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
|
|
||||||
"integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"eventemitter3": "^4.0.0",
|
|
||||||
"follow-redirects": "^1.0.0",
|
|
||||||
"requires-port": "^1.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/http-server": {
|
|
||||||
"version": "14.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/http-server/-/http-server-14.1.1.tgz",
|
|
||||||
"integrity": "sha512-+cbxadF40UXd9T01zUHgA+rlo2Bg1Srer4+B4NwIHdaGxAGGv59nYRnGGDJ9LBk7alpS0US+J+bLLdQOOkJq4A==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"basic-auth": "^2.0.1",
|
|
||||||
"chalk": "^4.1.2",
|
|
||||||
"corser": "^2.0.1",
|
|
||||||
"he": "^1.2.0",
|
|
||||||
"html-encoding-sniffer": "^3.0.0",
|
|
||||||
"http-proxy": "^1.18.1",
|
|
||||||
"mime": "^1.6.0",
|
|
||||||
"minimist": "^1.2.6",
|
|
||||||
"opener": "^1.5.1",
|
|
||||||
"portfinder": "^1.0.28",
|
|
||||||
"secure-compare": "3.0.1",
|
|
||||||
"union": "~0.5.0",
|
|
||||||
"url-join": "^4.0.1"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"http-server": "bin/http-server"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/iconv-lite": {
|
|
||||||
"version": "0.6.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
|
||||||
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.10.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/lodash": {
|
|
||||||
"version": "4.17.21",
|
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
|
||||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/mime": {
|
|
||||||
"version": "1.6.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
|
|
||||||
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
|
|
||||||
"dev": true,
|
|
||||||
"bin": {
|
|
||||||
"mime": "cli.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/minimist": {
|
|
||||||
"version": "1.2.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
|
||||||
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
|
||||||
"dev": true,
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/mkdirp": {
|
|
||||||
"version": "0.5.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
|
|
||||||
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"minimist": "^1.2.6"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"mkdirp": "bin/cmd.js"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"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==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"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==",
|
|
||||||
"dev": true,
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/opener": {
|
|
||||||
"version": "1.5.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz",
|
|
||||||
"integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==",
|
|
||||||
"dev": true,
|
|
||||||
"bin": {
|
|
||||||
"opener": "bin/opener-bin.js"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/portfinder": {
|
|
||||||
"version": "1.0.32",
|
|
||||||
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz",
|
|
||||||
"integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"async": "^2.6.4",
|
|
||||||
"debug": "^3.2.7",
|
|
||||||
"mkdirp": "^0.5.6"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.12.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/qs": {
|
|
||||||
"version": "6.11.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
|
|
||||||
"integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"side-channel": "^1.0.4"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.6"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/requires-port": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
|
||||||
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/safe-buffer": {
|
|
||||||
"version": "5.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
|
||||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/safer-buffer": {
|
|
||||||
"version": "2.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
|
||||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/secure-compare": {
|
|
||||||
"version": "3.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz",
|
|
||||||
"integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"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==",
|
|
||||||
"dev": true,
|
|
||||||
"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/supports-color": {
|
|
||||||
"version": "7.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
|
||||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"has-flag": "^4.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/union": {
|
|
||||||
"version": "0.5.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz",
|
|
||||||
"integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"qs": "^6.4.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.8.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/url-join": {
|
|
||||||
"version": "4.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz",
|
|
||||||
"integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/whatwg-encoding": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"iconv-lite": "0.6.3"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@fortawesome/fontawesome-free": {
|
|
||||||
"version": "6.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.2.0.tgz",
|
|
||||||
"integrity": "sha512-CNR7qRIfCwWHNN7FnKUniva94edPdyQzil/zCwk3v6k4R6rR2Fr8i4s3PM7n/lyfPA6Zfko9z5WDzFxG9SW1uQ=="
|
|
||||||
},
|
|
||||||
"@popperjs/core": {
|
|
||||||
"version": "2.11.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz",
|
|
||||||
"integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==",
|
|
||||||
"peer": true
|
|
||||||
},
|
|
||||||
"ansi-styles": {
|
|
||||||
"version": "4.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
|
||||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"color-convert": "^2.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"async": {
|
|
||||||
"version": "2.6.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
|
|
||||||
"integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"lodash": "^4.17.14"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"basic-auth": {
|
|
||||||
"version": "2.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
|
|
||||||
"integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"safe-buffer": "5.1.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"bootstrap": {
|
|
||||||
"version": "5.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.1.tgz",
|
|
||||||
"integrity": "sha512-UQi3v2NpVPEi1n35dmRRzBJFlgvWHYwyem6yHhuT6afYF+sziEt46McRbT//kVXZ7b1YUYEVGdXEH74Nx3xzGA==",
|
|
||||||
"requires": {}
|
|
||||||
},
|
|
||||||
"call-bind": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
|
|
||||||
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"function-bind": "^1.1.1",
|
|
||||||
"get-intrinsic": "^1.0.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"chalk": {
|
|
||||||
"version": "4.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
|
||||||
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"ansi-styles": "^4.1.0",
|
|
||||||
"supports-color": "^7.1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"color-convert": {
|
|
||||||
"version": "2.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
|
||||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"color-name": "~1.1.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"color-name": {
|
|
||||||
"version": "1.1.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
|
||||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"corser": {
|
|
||||||
"version": "2.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz",
|
|
||||||
"integrity": "sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"debug": {
|
|
||||||
"version": "3.2.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
|
|
||||||
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"ms": "^2.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"eventemitter3": {
|
|
||||||
"version": "4.0.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
|
|
||||||
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"follow-redirects": {
|
|
||||||
"version": "1.15.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
|
|
||||||
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"function-bind": {
|
|
||||||
"version": "1.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
|
||||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"get-intrinsic": {
|
|
||||||
"version": "1.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz",
|
|
||||||
"integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"function-bind": "^1.1.1",
|
|
||||||
"has": "^1.0.3",
|
|
||||||
"has-symbols": "^1.0.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"has": {
|
|
||||||
"version": "1.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
|
|
||||||
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"function-bind": "^1.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"has-flag": {
|
|
||||||
"version": "4.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
|
||||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"has-symbols": {
|
|
||||||
"version": "1.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
|
|
||||||
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"he": {
|
|
||||||
"version": "1.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
|
|
||||||
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"html-encoding-sniffer": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"whatwg-encoding": "^2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"http-proxy": {
|
|
||||||
"version": "1.18.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
|
|
||||||
"integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"eventemitter3": "^4.0.0",
|
|
||||||
"follow-redirects": "^1.0.0",
|
|
||||||
"requires-port": "^1.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"http-server": {
|
|
||||||
"version": "14.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/http-server/-/http-server-14.1.1.tgz",
|
|
||||||
"integrity": "sha512-+cbxadF40UXd9T01zUHgA+rlo2Bg1Srer4+B4NwIHdaGxAGGv59nYRnGGDJ9LBk7alpS0US+J+bLLdQOOkJq4A==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"basic-auth": "^2.0.1",
|
|
||||||
"chalk": "^4.1.2",
|
|
||||||
"corser": "^2.0.1",
|
|
||||||
"he": "^1.2.0",
|
|
||||||
"html-encoding-sniffer": "^3.0.0",
|
|
||||||
"http-proxy": "^1.18.1",
|
|
||||||
"mime": "^1.6.0",
|
|
||||||
"minimist": "^1.2.6",
|
|
||||||
"opener": "^1.5.1",
|
|
||||||
"portfinder": "^1.0.28",
|
|
||||||
"secure-compare": "3.0.1",
|
|
||||||
"union": "~0.5.0",
|
|
||||||
"url-join": "^4.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"iconv-lite": {
|
|
||||||
"version": "0.6.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
|
||||||
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lodash": {
|
|
||||||
"version": "4.17.21",
|
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
|
||||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"mime": {
|
|
||||||
"version": "1.6.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
|
|
||||||
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"minimist": {
|
|
||||||
"version": "1.2.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
|
||||||
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"mkdirp": {
|
|
||||||
"version": "0.5.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
|
|
||||||
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"minimist": "^1.2.6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ms": {
|
|
||||||
"version": "2.1.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
|
||||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"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==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"opener": {
|
|
||||||
"version": "1.5.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz",
|
|
||||||
"integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"portfinder": {
|
|
||||||
"version": "1.0.32",
|
|
||||||
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz",
|
|
||||||
"integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"async": "^2.6.4",
|
|
||||||
"debug": "^3.2.7",
|
|
||||||
"mkdirp": "^0.5.6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"qs": {
|
|
||||||
"version": "6.11.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
|
|
||||||
"integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"side-channel": "^1.0.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"requires-port": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
|
||||||
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"safe-buffer": {
|
|
||||||
"version": "5.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
|
||||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"safer-buffer": {
|
|
||||||
"version": "2.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
|
||||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"secure-compare": {
|
|
||||||
"version": "3.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz",
|
|
||||||
"integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"side-channel": {
|
|
||||||
"version": "1.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
|
|
||||||
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"call-bind": "^1.0.0",
|
|
||||||
"get-intrinsic": "^1.0.2",
|
|
||||||
"object-inspect": "^1.9.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"supports-color": {
|
|
||||||
"version": "7.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
|
||||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"has-flag": "^4.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"union": {
|
|
||||||
"version": "0.5.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz",
|
|
||||||
"integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"qs": "^6.4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"url-join": {
|
|
||||||
"version": "4.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz",
|
|
||||||
"integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"whatwg-encoding": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"iconv-lite": "0.6.3"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "int-prog",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"main": "index.html",
|
|
||||||
"scripts": {
|
|
||||||
"start": "http-server -p 3000 ./",
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"bootstrap": "5.2.1",
|
|
||||||
"@fortawesome/fontawesome-free": "6.2.0"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"http-server": "14.1.1"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
const calculateButton = document.getElementById("calculate");
|
|
||||||
const first = document.getElementById("first");
|
|
||||||
const second = document.getElementById("second");
|
|
||||||
const select = document.getElementById("operation");
|
|
||||||
const result = document.getElementById("result");
|
|
||||||
|
|
||||||
calculateButton.onclick = function() {
|
|
||||||
calculate();
|
|
||||||
};
|
|
||||||
|
|
||||||
function calculate() {
|
|
||||||
switch (parseInt(select.value)) {
|
|
||||||
case 1:
|
|
||||||
doSmth("plus")
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
doSmth("minus")
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
doSmth("mult")
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
doSmth("div")
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkNum(res) {
|
|
||||||
if (res.indexOf(".") != -1)
|
|
||||||
return parseInt(res)
|
|
||||||
else
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
function doSmth(address) {
|
|
||||||
fetch(`http://localhost:8080/${address}?first=${first.value}&second=${second.value}`)
|
|
||||||
.then(response => response.text())
|
|
||||||
.then(res => result.innerHTML = checkNum(res));
|
|
||||||
}
|
|
@ -1 +1,2 @@
|
|||||||
rootProject.name = 'app'
|
rootProject.name = 'app'
|
||||||
|
include 'front'
|
@ -2,8 +2,6 @@ package com.labwork1.app;
|
|||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
@ -12,32 +10,4 @@ public class AppApplication {
|
|||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
SpringApplication.run(AppApplication.class, args);
|
SpringApplication.run(AppApplication.class, args);
|
||||||
}
|
}
|
||||||
@GetMapping("/hello")
|
|
||||||
public String hello(@RequestParam(value = "name", defaultValue = "World") String name) {
|
|
||||||
return String.format("Hello %s!", name);
|
|
||||||
}
|
|
||||||
@GetMapping("/plus")
|
|
||||||
public String plus(@RequestParam(required = false, defaultValue = "0") double first,
|
|
||||||
@RequestParam(required = false, defaultValue = "0") double second) {
|
|
||||||
return Double.toString(first + second);
|
|
||||||
}
|
|
||||||
@GetMapping("/minus")
|
|
||||||
public String minus(@RequestParam(required = false, defaultValue = "0") double first,
|
|
||||||
@RequestParam(required = false, defaultValue = "0") double second) {
|
|
||||||
return Double.toString(first - second);
|
|
||||||
}
|
|
||||||
@GetMapping("/mult")
|
|
||||||
public String mult(@RequestParam(required = false, defaultValue = "1") double first,
|
|
||||||
@RequestParam(required = false, defaultValue = "1") double second) {
|
|
||||||
return Double.toString(first * second);
|
|
||||||
}
|
|
||||||
@GetMapping("/div")
|
|
||||||
public String div(@RequestParam(required = false, defaultValue = "1") double first,
|
|
||||||
@RequestParam(required = false, defaultValue = "1") double second) {
|
|
||||||
if(second == 0)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return Double.toString(first/second);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
package com.labwork1.app;
|
|
||||||
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
|
||||||
@Configuration
|
|
||||||
public class WebConfiguration implements WebMvcConfigurer {
|
|
||||||
@Override
|
|
||||||
public void addCorsMappings(CorsRegistry registry) {
|
|
||||||
registry.addMapping("/**").allowedMethods("*");
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,28 @@
|
|||||||
|
package com.labwork1.app.configuration;
|
||||||
|
|
||||||
|
import com.labwork1.app.configuration.jwt.JwtFilter;
|
||||||
|
import io.swagger.v3.oas.models.Components;
|
||||||
|
import io.swagger.v3.oas.models.OpenAPI;
|
||||||
|
import io.swagger.v3.oas.models.security.SecurityRequirement;
|
||||||
|
import io.swagger.v3.oas.models.security.SecurityScheme;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class OpenAPI30Configuration {
|
||||||
|
public static final String API_PREFIX = "/api/1.0";
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public OpenAPI customizeOpenAPI() {
|
||||||
|
final String securitySchemeName = JwtFilter.TOKEN_BEGIN_STR;
|
||||||
|
return new OpenAPI()
|
||||||
|
.addSecurityItem(new SecurityRequirement()
|
||||||
|
.addList(securitySchemeName))
|
||||||
|
.components(new Components()
|
||||||
|
.addSecuritySchemes(securitySchemeName, new SecurityScheme()
|
||||||
|
.name(securitySchemeName)
|
||||||
|
.type(SecurityScheme.Type.HTTP)
|
||||||
|
.scheme("bearer")
|
||||||
|
.bearerFormat("JWT")));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package com.labwork1.app.configuration;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class PasswordEncoderConfiguration {
|
||||||
|
@Bean
|
||||||
|
public PasswordEncoder passwordEncoder() {
|
||||||
|
return new BCryptPasswordEncoder();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,87 @@
|
|||||||
|
package com.labwork1.app.configuration;
|
||||||
|
|
||||||
|
import com.labwork1.app.configuration.jwt.JwtFilter;
|
||||||
|
import com.labwork1.app.student.controller.UserController;
|
||||||
|
import com.labwork1.app.student.model.UserRole;
|
||||||
|
import com.labwork1.app.student.service.UserService;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
|
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
|
||||||
|
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class SecurityConfiguration {
|
||||||
|
private final Logger log = LoggerFactory.getLogger(SecurityConfiguration.class);
|
||||||
|
public static final String SPA_URL_MASK = "/{path:[^\\.]*}";
|
||||||
|
private final UserService userService;
|
||||||
|
private final JwtFilter jwtFilter;
|
||||||
|
|
||||||
|
public SecurityConfiguration(UserService userService) {
|
||||||
|
this.userService = userService;
|
||||||
|
this.jwtFilter = new JwtFilter(userService);
|
||||||
|
createAdminOnStartup();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createAdminOnStartup() {
|
||||||
|
final String admin = "admin";
|
||||||
|
if (userService.findByLogin(admin) == null) {
|
||||||
|
log.info("Admin user successfully created");
|
||||||
|
userService.createUser(admin, admin, admin, UserRole.ADMIN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||||
|
log.info("Creating security configuration");
|
||||||
|
http.cors()
|
||||||
|
.and()
|
||||||
|
.csrf().disable()
|
||||||
|
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
||||||
|
.and()
|
||||||
|
.authorizeHttpRequests()
|
||||||
|
.requestMatchers("/", SPA_URL_MASK).permitAll()
|
||||||
|
.requestMatchers(HttpMethod.POST, UserController.URL_LOGIN).permitAll()
|
||||||
|
.requestMatchers(HttpMethod.POST, UserController.URL_SIGNUP).permitAll()
|
||||||
|
.requestMatchers(HttpMethod.POST, UserController.URL_GET_ROLE).permitAll()
|
||||||
|
.anyRequest()
|
||||||
|
.authenticated()
|
||||||
|
.and()
|
||||||
|
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)
|
||||||
|
.anonymous();
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public AuthenticationManager authenticationManagerBean(HttpSecurity http) throws Exception {
|
||||||
|
AuthenticationManagerBuilder authenticationManagerBuilder = http
|
||||||
|
.getSharedObject(AuthenticationManagerBuilder.class);
|
||||||
|
authenticationManagerBuilder.userDetailsService(userService);
|
||||||
|
return authenticationManagerBuilder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public WebSecurityCustomizer webSecurityCustomizer() {
|
||||||
|
return web -> web.ignoring()
|
||||||
|
.requestMatchers(HttpMethod.OPTIONS, "/**")
|
||||||
|
.requestMatchers("/*.js")
|
||||||
|
.requestMatchers("/*.html")
|
||||||
|
.requestMatchers("/*.css")
|
||||||
|
.requestMatchers("/*.png")
|
||||||
|
.requestMatchers("/*.jpg")
|
||||||
|
.requestMatchers("/favicon.ico")
|
||||||
|
.requestMatchers("/swagger-ui/index.html")
|
||||||
|
.requestMatchers("/webjars/**")
|
||||||
|
.requestMatchers("/swagger-resources/**")
|
||||||
|
.requestMatchers("/v3/api-docs/**")
|
||||||
|
.requestMatchers("/h2-console/**");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package com.labwork1.app.configuration;
|
||||||
|
|
||||||
|
import org.springframework.boot.web.server.ErrorPage;
|
||||||
|
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
|
||||||
|
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
class WebConfiguration implements WebMvcConfigurer {
|
||||||
|
@Override
|
||||||
|
public void addViewControllers(ViewControllerRegistry registry) {
|
||||||
|
registry.addViewController(SecurityConfiguration.SPA_URL_MASK).setViewName("forward:/");
|
||||||
|
registry.addViewController("/notFound").setViewName("forward:/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> containerCustomizer() {
|
||||||
|
return container -> container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/notFound"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addCorsMappings(CorsRegistry registry) {
|
||||||
|
registry.addMapping("/**").allowedMethods("*");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
|||||||
|
package com.labwork1.app.configuration.jwt;
|
||||||
|
|
||||||
|
public class JwtException extends RuntimeException {
|
||||||
|
public JwtException(Throwable throwable) {
|
||||||
|
super(throwable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JwtException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
package com.labwork1.app.configuration.jwt;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.labwork1.app.student.service.UserService;
|
||||||
|
import jakarta.servlet.FilterChain;
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.ServletRequest;
|
||||||
|
import jakarta.servlet.ServletResponse;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.web.filter.GenericFilterBean;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class JwtFilter extends GenericFilterBean {
|
||||||
|
private static final String AUTHORIZATION = "Authorization";
|
||||||
|
public static final String TOKEN_BEGIN_STR = "Bearer ";
|
||||||
|
|
||||||
|
private final UserService userService;
|
||||||
|
|
||||||
|
public JwtFilter(UserService userService) {
|
||||||
|
this.userService = userService;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getTokenFromRequest(HttpServletRequest request) {
|
||||||
|
String bearer = request.getHeader(AUTHORIZATION);
|
||||||
|
if (StringUtils.hasText(bearer) && bearer.startsWith(TOKEN_BEGIN_STR)) {
|
||||||
|
return bearer.substring(TOKEN_BEGIN_STR.length());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void raiseException(ServletResponse response, int status, String message) throws IOException {
|
||||||
|
if (response instanceof final HttpServletResponse httpResponse) {
|
||||||
|
httpResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||||
|
httpResponse.setStatus(status);
|
||||||
|
final byte[] body = new ObjectMapper().writeValueAsBytes(message);
|
||||||
|
response.getOutputStream().write(body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doFilter(ServletRequest request,
|
||||||
|
ServletResponse response,
|
||||||
|
FilterChain chain) throws IOException, ServletException {
|
||||||
|
if (request instanceof final HttpServletRequest httpRequest) {
|
||||||
|
final String token = getTokenFromRequest(httpRequest);
|
||||||
|
if (StringUtils.hasText(token)) {
|
||||||
|
try {
|
||||||
|
final UserDetails user = userService.loadUserByToken(token);
|
||||||
|
final UsernamePasswordAuthenticationToken auth =
|
||||||
|
new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||||
|
} catch (JwtException e) {
|
||||||
|
raiseException(response, HttpServletResponse.SC_UNAUTHORIZED, e.getMessage());
|
||||||
|
return;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
raiseException(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
|
||||||
|
String.format("Internal error: %s", e.getMessage()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chain.doFilter(request, response);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package com.labwork1.app.configuration.jwt;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ConfigurationProperties(prefix = "jwt", ignoreInvalidFields = true)
|
||||||
|
public class JwtProperties {
|
||||||
|
private String devToken = "";
|
||||||
|
private Boolean isDev = true;
|
||||||
|
|
||||||
|
public String getDevToken() {
|
||||||
|
return devToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDevToken(String devToken) {
|
||||||
|
this.devToken = devToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean isDev() {
|
||||||
|
return isDev;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDev(Boolean dev) {
|
||||||
|
isDev = dev;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,107 @@
|
|||||||
|
package com.labwork1.app.configuration.jwt;
|
||||||
|
|
||||||
|
import com.auth0.jwt.JWT;
|
||||||
|
import com.auth0.jwt.algorithms.Algorithm;
|
||||||
|
import com.auth0.jwt.exceptions.JWTVerificationException;
|
||||||
|
import com.auth0.jwt.interfaces.DecodedJWT;
|
||||||
|
import com.auth0.jwt.interfaces.JWTVerifier;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class JwtProvider {
|
||||||
|
private final static Logger LOG = LoggerFactory.getLogger(JwtProvider.class);
|
||||||
|
|
||||||
|
private final static byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(StandardCharsets.US_ASCII);
|
||||||
|
private final static String ISSUER = "auth0";
|
||||||
|
|
||||||
|
private final Algorithm algorithm;
|
||||||
|
private final JWTVerifier verifier;
|
||||||
|
|
||||||
|
public JwtProvider(JwtProperties jwtProperties) {
|
||||||
|
if (!jwtProperties.isDev()) {
|
||||||
|
LOG.info("Generate new JWT key for prod");
|
||||||
|
try {
|
||||||
|
final MessageDigest salt = MessageDigest.getInstance("SHA-256");
|
||||||
|
salt.update(UUID.randomUUID().toString().getBytes(StandardCharsets.UTF_8));
|
||||||
|
LOG.info("Use generated JWT key for prod \n{}", bytesToHex(salt.digest()));
|
||||||
|
algorithm = Algorithm.HMAC256(bytesToHex(salt.digest()));
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new JwtException(e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOG.info("Use default JWT key for dev \n{}", jwtProperties.getDevToken());
|
||||||
|
algorithm = Algorithm.HMAC256(jwtProperties.getDevToken());
|
||||||
|
}
|
||||||
|
verifier = JWT.require(algorithm)
|
||||||
|
.withIssuer(ISSUER)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String bytesToHex(byte[] bytes) {
|
||||||
|
byte[] hexChars = new byte[bytes.length * 2];
|
||||||
|
for (int j = 0; j < bytes.length; j++) {
|
||||||
|
int v = bytes[j] & 0xFF;
|
||||||
|
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
|
||||||
|
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
|
||||||
|
}
|
||||||
|
return new String(hexChars, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String generateToken(String login) {
|
||||||
|
final Date issueDate = Date.from(LocalDate.now()
|
||||||
|
.atStartOfDay(ZoneId.systemDefault())
|
||||||
|
.toInstant());
|
||||||
|
final Date expireDate = Date.from(LocalDate.now()
|
||||||
|
.plusDays(15)
|
||||||
|
.atStartOfDay(ZoneId.systemDefault())
|
||||||
|
.toInstant());
|
||||||
|
return JWT.create()
|
||||||
|
.withIssuer(ISSUER)
|
||||||
|
.withIssuedAt(issueDate)
|
||||||
|
.withExpiresAt(expireDate)
|
||||||
|
.withSubject(login)
|
||||||
|
.sign(algorithm);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DecodedJWT validateToken(String token) {
|
||||||
|
try {
|
||||||
|
return verifier.verify(token);
|
||||||
|
} catch (JWTVerificationException e) {
|
||||||
|
throw new JwtException(String.format("Token verification error: %s", e.getMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTokenValid(String token) {
|
||||||
|
if (!StringUtils.hasText(token)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
validateToken(token);
|
||||||
|
return true;
|
||||||
|
} catch (JwtException e) {
|
||||||
|
LOG.error(e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<String> getLoginFromToken(String token) {
|
||||||
|
try {
|
||||||
|
return Optional.ofNullable(validateToken(token).getSubject());
|
||||||
|
} catch (JwtException e) {
|
||||||
|
LOG.error(e.getMessage());
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
package com.labwork1.app.student.controller;
|
||||||
|
|
||||||
|
import com.labwork1.app.student.model.UserRole;
|
||||||
|
import com.labwork1.app.student.service.CinemaService;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import org.springframework.security.access.annotation.Secured;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/cinema")
|
||||||
|
public class CinemaController {
|
||||||
|
private final CinemaService cinemaService;
|
||||||
|
|
||||||
|
public CinemaController(CinemaService cinemaService) {
|
||||||
|
this.cinemaService = cinemaService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public CinemaDto getCinema(@PathVariable Long id) {
|
||||||
|
return new CinemaDto(cinemaService.findCinema(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
public List<CinemaDto> getCinemas() {
|
||||||
|
return cinemaService.findAllCinemas().stream()
|
||||||
|
.map(CinemaDto::new)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/search")
|
||||||
|
public List<CinemaDto> getCinemas(@RequestParam("request") String request) {
|
||||||
|
return cinemaService.findAllCinemas(request).stream()
|
||||||
|
.map(CinemaDto::new)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
@Secured({UserRole.AsString.ADMIN})
|
||||||
|
public CinemaDto createCinema(@RequestBody @Valid CinemaDto cinemaDto) {
|
||||||
|
return new CinemaDto(cinemaService.addCinema(cinemaDto));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/{id}")
|
||||||
|
@Secured({UserRole.AsString.ADMIN})
|
||||||
|
public CinemaDto updateCinema(@RequestBody @Valid CinemaDto cinemaDto) {
|
||||||
|
return new CinemaDto(cinemaService.updateCinema(cinemaDto));
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/{id}")
|
||||||
|
@Secured({UserRole.AsString.ADMIN})
|
||||||
|
public CinemaDto deleteCinema(@PathVariable Long id) {
|
||||||
|
return new CinemaDto(cinemaService.deleteCinema(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
package com.labwork1.app.student.controller;
|
||||||
|
|
||||||
|
import com.labwork1.app.student.model.Cinema;
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
public class CinemaDto {
|
||||||
|
private long id;
|
||||||
|
@NotBlank
|
||||||
|
private String name;
|
||||||
|
private String image;
|
||||||
|
@NotBlank
|
||||||
|
private String description;
|
||||||
|
@NotNull
|
||||||
|
private Long year;
|
||||||
|
|
||||||
|
public CinemaDto() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public CinemaDto(Cinema cinema) {
|
||||||
|
this.id = cinema.getId();
|
||||||
|
this.name = cinema.getName();
|
||||||
|
this.description = cinema.getDescription();
|
||||||
|
this.year = cinema.getYear();
|
||||||
|
this.image = new String(cinema.getImage(), StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getYear() {
|
||||||
|
return year;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getImage() {
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
package com.labwork1.app.student.controller;
|
||||||
|
|
||||||
|
import com.labwork1.app.student.service.OrderService;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/order")
|
||||||
|
public class OrderController {
|
||||||
|
private final OrderService orderService;
|
||||||
|
|
||||||
|
public OrderController(OrderService orderService) {
|
||||||
|
this.orderService = orderService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public OrderDto getOrder(@PathVariable Long id) {
|
||||||
|
return new OrderDto(orderService.findOrder(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
public List<OrderDto> getOrders() {
|
||||||
|
return orderService.findAllOrders().stream()
|
||||||
|
.map(OrderDto::new)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/{user}")
|
||||||
|
public OrderDto createOrder(@PathVariable String user) {
|
||||||
|
return new OrderDto(orderService.addOrder(user));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/{id}")
|
||||||
|
public OrderDto updateOrder(@PathVariable Long id,
|
||||||
|
@RequestParam("session") Long session,
|
||||||
|
@RequestParam(value = "count", required = false) Integer count) {
|
||||||
|
if (count == null)
|
||||||
|
return new OrderDto(orderService.deleteSessionInOrder(id, session, Integer.MAX_VALUE));
|
||||||
|
if (count > 0)
|
||||||
|
return new OrderDto(orderService.addSession(id, session, count));
|
||||||
|
return new OrderDto(orderService.deleteSessionInOrder(id, session, -count));
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/{id}")
|
||||||
|
public OrderDto deleteOrder(@PathVariable Long id) {
|
||||||
|
return new OrderDto(orderService.deleteOrder(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package com.labwork1.app.student.controller;
|
||||||
|
|
||||||
|
import com.labwork1.app.student.model.User;
|
||||||
|
import com.labwork1.app.student.model.Order;
|
||||||
|
import com.labwork1.app.student.model.OrderSession;
|
||||||
|
|
||||||
|
import java.sql.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class OrderDto {
|
||||||
|
private long id;
|
||||||
|
private String user;
|
||||||
|
private List<OrderSessionDto> sessions;
|
||||||
|
|
||||||
|
public OrderDto() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public OrderDto(Order order) {
|
||||||
|
this.id = order.getId();
|
||||||
|
this.user = order.getUser().getLogin();
|
||||||
|
if (order.getSessions() != null && order.getSessions().size() > 0)
|
||||||
|
this.sessions = order.getSessions()
|
||||||
|
.stream()
|
||||||
|
.map(x -> new OrderSessionDto(new SessionDto(x.getSession()),
|
||||||
|
x.getId().getOrderId(), x.getCount())).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<OrderSessionDto> getSessions() {
|
||||||
|
return sessions;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package com.labwork1.app.student.controller;
|
||||||
|
|
||||||
|
public class OrderSessionDto {
|
||||||
|
private SessionDto session;
|
||||||
|
private Long orderId;
|
||||||
|
private Integer count;
|
||||||
|
|
||||||
|
public OrderSessionDto() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public OrderSessionDto(SessionDto session, Long orderId, Integer count) {
|
||||||
|
this.session = session;
|
||||||
|
this.orderId = orderId;
|
||||||
|
this.count = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SessionDto getSession() {
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getOrderId() {
|
||||||
|
return orderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getCount() {
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package com.labwork1.app.student.controller;
|
||||||
|
|
||||||
|
import com.labwork1.app.student.model.UserRole;
|
||||||
|
import com.labwork1.app.student.service.SessionService;
|
||||||
|
import org.springframework.security.access.annotation.Secured;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/session")
|
||||||
|
public class SessionController {
|
||||||
|
private final SessionService sessionService;
|
||||||
|
|
||||||
|
public SessionController(SessionService sessionService) {
|
||||||
|
this.sessionService = sessionService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public SessionDto getSession(@PathVariable Long id) {
|
||||||
|
return new SessionDto(sessionService.findSession(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
public List<SessionDto> getSessions() {
|
||||||
|
return sessionService.findAllSessions().stream()
|
||||||
|
.map(SessionDto::new)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
@Secured({UserRole.AsString.ADMIN})
|
||||||
|
public SessionDto createSession(@RequestParam("price") String price,
|
||||||
|
@RequestParam("dateTime") String dateTime,
|
||||||
|
@RequestParam("cinemaid") Long cinemaId,
|
||||||
|
@RequestParam("capacity") Integer capacity) throws ParseException {
|
||||||
|
SimpleDateFormat format = new SimpleDateFormat();
|
||||||
|
format.applyPattern("yyyy-MM-dd-HH:ss");
|
||||||
|
Date docDate = format.parse(dateTime.replace('T', '-'));
|
||||||
|
return new SessionDto(sessionService.findSession(
|
||||||
|
sessionService.addSession(Double.parseDouble(price),
|
||||||
|
new Timestamp(docDate.getTime()), cinemaId, capacity).getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/{id}")
|
||||||
|
@Secured({UserRole.AsString.ADMIN})
|
||||||
|
public SessionDto updateSession(@PathVariable Long id,
|
||||||
|
@RequestParam("price") String price) {
|
||||||
|
return new SessionDto(sessionService.findSession(sessionService
|
||||||
|
.updateSession(id, Double.parseDouble(price)).getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/{id}")
|
||||||
|
@Secured({UserRole.AsString.ADMIN})
|
||||||
|
public SessionDto deleteSession(@PathVariable Long id) {
|
||||||
|
return new SessionDto(sessionService.deleteSession(id));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
package com.labwork1.app.student.controller;
|
||||||
|
|
||||||
|
import com.labwork1.app.student.model.Session;
|
||||||
|
import com.labwork1.app.student.model.SessionExtension;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
|
||||||
|
public class SessionDto {
|
||||||
|
private long id;
|
||||||
|
private Double price;
|
||||||
|
private Timestamp dateTime;
|
||||||
|
private CinemaDto cinema;
|
||||||
|
private Long capacity;
|
||||||
|
|
||||||
|
private int maxCount;
|
||||||
|
|
||||||
|
public SessionDto() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public SessionDto(SessionExtension session) {
|
||||||
|
this.id = session.getId();
|
||||||
|
this.price = session.getPrice();
|
||||||
|
this.dateTime = session.getTimestamp();
|
||||||
|
this.capacity = session.getCapacity();
|
||||||
|
this.maxCount = session.getMaxCount();
|
||||||
|
if (session.getCinema() != null) {
|
||||||
|
this.cinema = new CinemaDto(session.getCinema());
|
||||||
|
} else this.cinema = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SessionDto(Session session) {
|
||||||
|
this.id = session.getId();
|
||||||
|
this.price = session.getPrice();
|
||||||
|
this.dateTime = session.getTimestamp();
|
||||||
|
this.maxCount = session.getMaxCount();
|
||||||
|
if (session.getCinema() != null) {
|
||||||
|
this.cinema = new CinemaDto(session.getCinema());
|
||||||
|
} else this.cinema = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxCount() {
|
||||||
|
return maxCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getPrice() {
|
||||||
|
return price;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Timestamp getTimestamp() {
|
||||||
|
return dateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getCapacity() {
|
||||||
|
return capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CinemaDto getCinema() {
|
||||||
|
return cinema;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,88 @@
|
|||||||
|
package com.labwork1.app.student.controller;
|
||||||
|
|
||||||
|
import com.labwork1.app.configuration.OpenAPI30Configuration;
|
||||||
|
import com.labwork1.app.student.model.User;
|
||||||
|
import com.labwork1.app.student.model.UserRole;
|
||||||
|
import com.labwork1.app.student.service.UserService;
|
||||||
|
import com.labwork1.app.util.validation.ValidationException;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.security.access.annotation.Secured;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
public class UserController {
|
||||||
|
private final UserService userService;
|
||||||
|
public static final String URL_LOGIN = "/jwt/login";
|
||||||
|
public static final String URL_SIGNUP = "/signup";
|
||||||
|
public static final String URL_MAIN = "/user";
|
||||||
|
public static final String URL_GET_ROLE = "/get-role";
|
||||||
|
public UserController(UserService userService) {
|
||||||
|
this.userService = userService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping(URL_LOGIN)
|
||||||
|
public String login(@RequestBody @Valid UserDto userDto) {
|
||||||
|
return userService.loginAndGetToken(userDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping(URL_SIGNUP)
|
||||||
|
public String signup(@RequestBody @Valid UserSignupDto userSignupDto){
|
||||||
|
try {
|
||||||
|
User user = userService.addUser(userSignupDto.getLogin(), userSignupDto.getPassword(), userSignupDto.getPasswordConfirm());
|
||||||
|
return user.getLogin() + " was created";
|
||||||
|
}
|
||||||
|
catch(ValidationException e){
|
||||||
|
return e.getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping(URL_MAIN + "/{id}")
|
||||||
|
public UserDto getUser(@PathVariable Long id) {
|
||||||
|
return new UserDto(userService.findUser(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping(URL_MAIN)
|
||||||
|
public UserDto getUserByLogin(@RequestParam("login") String login) {
|
||||||
|
return new UserDto(userService.findByLogin(login));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping(URL_GET_ROLE)
|
||||||
|
public String getRole(@RequestParam("token") String token) {
|
||||||
|
UserDetails userDetails = userService.loadUserByToken(token);
|
||||||
|
User user = userService.findByLogin(userDetails.getUsername());
|
||||||
|
return user.getRole().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping(OpenAPI30Configuration.API_PREFIX + URL_MAIN)
|
||||||
|
@Secured({UserRole.AsString.ADMIN})
|
||||||
|
public Page<UserDto> getUsers(@RequestParam(defaultValue = "1") int page,
|
||||||
|
@RequestParam(defaultValue = "5") int size) {
|
||||||
|
return userService.findAllPages(page, size)
|
||||||
|
.map(UserDto::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping(URL_MAIN + "/{id}")
|
||||||
|
@Secured({UserRole.AsString.ADMIN})
|
||||||
|
public UserDto updateUser(@PathVariable Long id,
|
||||||
|
@RequestBody @Valid UserDto userDto) {
|
||||||
|
return new UserDto(userService.updateUser(id, userDto.getLogin(), userDto.getPassword()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/{id}")
|
||||||
|
public UserDto updateUserCart(@PathVariable Long id,
|
||||||
|
@RequestParam("session") Long session,
|
||||||
|
@RequestParam(value = "count", required = false) Integer count) {
|
||||||
|
if (count == null)
|
||||||
|
return new UserDto(userService.deleteSessionInCart(id, session, Integer.MAX_VALUE));
|
||||||
|
if (count > 0)
|
||||||
|
return new UserDto(userService.addSession(id, session, count));
|
||||||
|
return new UserDto(userService.deleteSessionInCart(id, session, -count));
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping(URL_MAIN + "/{id}")
|
||||||
|
public UserDto deleteUser(@PathVariable Long id) {
|
||||||
|
return new UserDto(userService.deleteUser(id));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package com.labwork1.app.student.controller;
|
||||||
|
|
||||||
|
import com.labwork1.app.student.model.User;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class UserDto {
|
||||||
|
private long id;
|
||||||
|
private String login;
|
||||||
|
private String password;
|
||||||
|
private List<OrderDto> orders;
|
||||||
|
private List<UserSessionDto> sessions;
|
||||||
|
|
||||||
|
public UserDto() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserDto(User user) {
|
||||||
|
this.id = user.getId();
|
||||||
|
this.login = user.getLogin();
|
||||||
|
this.password = user.getPassword();
|
||||||
|
this.orders = new ArrayList<>();
|
||||||
|
if (user.getOrders() != null) {
|
||||||
|
orders = user.getOrders().stream()
|
||||||
|
.map(OrderDto::new).toList();
|
||||||
|
}
|
||||||
|
if (user.getSessions() != null && user.getSessions().size() > 0)
|
||||||
|
this.sessions = user.getSessions()
|
||||||
|
.stream()
|
||||||
|
.map(x -> new UserSessionDto(new SessionDto(x.getSession()),
|
||||||
|
x.getId().getUserId(), x.getCount())).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLogin() {
|
||||||
|
return login;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<OrderDto> getOrders() {
|
||||||
|
return orders;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<UserSessionDto> getSessions() {
|
||||||
|
return sessions;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package com.labwork1.app.student.controller;
|
||||||
|
|
||||||
|
public class UserSessionDto {
|
||||||
|
private SessionDto session;
|
||||||
|
private Long userId;
|
||||||
|
private Integer count;
|
||||||
|
|
||||||
|
public UserSessionDto() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserSessionDto(SessionDto session, Long userId, Integer count) {
|
||||||
|
this.session = session;
|
||||||
|
this.userId = userId;
|
||||||
|
this.count = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SessionDto getSession() {
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getCount() {
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package com.labwork1.app.student.controller;
|
||||||
|
|
||||||
|
public class UserSignupDto {
|
||||||
|
private String login;
|
||||||
|
private String password;
|
||||||
|
private String passwordConfirm;
|
||||||
|
|
||||||
|
public String getLogin() {
|
||||||
|
return login;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLogin(String login) {
|
||||||
|
this.login = login;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPasswordConfirm() {
|
||||||
|
return passwordConfirm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPasswordConfirm(String passwordConfirm) {
|
||||||
|
this.passwordConfirm = passwordConfirm;
|
||||||
|
}
|
||||||
|
}
|
90
src/main/java/com/labwork1/app/student/model/Cinema.java
Normal file
90
src/main/java/com/labwork1/app/student/model/Cinema.java
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
package com.labwork1.app.student.model;
|
||||||
|
|
||||||
|
import com.labwork1.app.student.controller.CinemaDto;
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class Cinema {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||||
|
private Long id;
|
||||||
|
@NotBlank(message = "name can't be null or empty")
|
||||||
|
@Column
|
||||||
|
private String name;
|
||||||
|
@NotBlank(message = "description can't be null or empty")
|
||||||
|
@Column
|
||||||
|
private String description;
|
||||||
|
@NotNull(message = "year can't be null or empty")
|
||||||
|
@Column(name = "col_year")
|
||||||
|
private Long year;
|
||||||
|
@OneToMany(fetch = FetchType.EAGER, mappedBy = "cinema", cascade = CascadeType.REMOVE)
|
||||||
|
private List<Session> sessions;
|
||||||
|
@Lob
|
||||||
|
private byte[] image;
|
||||||
|
|
||||||
|
public Cinema() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cinema(CinemaDto cinemaDto) {
|
||||||
|
this.name = cinemaDto.getName();
|
||||||
|
this.description = cinemaDto.getDescription();
|
||||||
|
this.year = cinemaDto.getYear();
|
||||||
|
this.image = cinemaDto.getImage().getBytes();
|
||||||
|
this.sessions = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getImage() {
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setImage(byte[] image) {
|
||||||
|
this.image = image;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Session> getSessions() {
|
||||||
|
return sessions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSession(Session session) {
|
||||||
|
if (session.getCinema().equals(this)) {
|
||||||
|
this.sessions.add(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getYear() {
|
||||||
|
return year;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setYear(Long year) {
|
||||||
|
this.year = year;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
86
src/main/java/com/labwork1/app/student/model/Order.java
Normal file
86
src/main/java/com/labwork1/app/student/model/Order.java
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
package com.labwork1.app.student.model;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
import java.sql.Date;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "tab_order")
|
||||||
|
public class Order {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||||
|
private Long id;
|
||||||
|
@ManyToOne(fetch = FetchType.EAGER)
|
||||||
|
@JoinColumn(name = "user_fk")
|
||||||
|
private User user;
|
||||||
|
@OneToMany(mappedBy = "order", fetch = FetchType.EAGER, cascade =
|
||||||
|
{
|
||||||
|
CascadeType.REMOVE,
|
||||||
|
CascadeType.MERGE,
|
||||||
|
CascadeType.PERSIST
|
||||||
|
}, orphanRemoval = true)
|
||||||
|
private List<OrderSession> sessions;
|
||||||
|
|
||||||
|
public Order() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSession(OrderSession orderSession) {
|
||||||
|
if (sessions == null) {
|
||||||
|
sessions = new ArrayList<>();
|
||||||
|
}
|
||||||
|
if (!sessions.contains(orderSession))
|
||||||
|
this.sessions.add(orderSession);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeSession(OrderSession orderSession){
|
||||||
|
if (sessions.contains(orderSession))
|
||||||
|
this.sessions.remove(orderSession);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
Order order = (Order) o;
|
||||||
|
return Objects.equals(id, order.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Order {" +
|
||||||
|
"id=" + id +
|
||||||
|
", user='" + user.toString() + '\'';
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUser(User user) {
|
||||||
|
this.user = user;
|
||||||
|
if (!user.getOrders().contains(this)) {
|
||||||
|
user.setOrder(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<OrderSession> getSessions() {
|
||||||
|
return sessions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSessions(List<OrderSession> sessions) {
|
||||||
|
this.sessions = sessions;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package com.labwork1.app.student.model;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "order_session")
|
||||||
|
public class OrderSession {
|
||||||
|
@EmbeddedId
|
||||||
|
private OrderSessionKey id;
|
||||||
|
@ManyToOne
|
||||||
|
@MapsId("sessionId")
|
||||||
|
@JoinColumn(name = "session_id")
|
||||||
|
private Session session;
|
||||||
|
@ManyToOne
|
||||||
|
@MapsId("orderId")
|
||||||
|
@JoinColumn(name = "order_id")
|
||||||
|
private Order order;
|
||||||
|
@Column(name = "count")
|
||||||
|
private Integer count;
|
||||||
|
|
||||||
|
public OrderSession() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public OrderSession(Order order, Session session, Integer count) {
|
||||||
|
this.order = order;
|
||||||
|
this.session = session;
|
||||||
|
this.count = count;
|
||||||
|
this.id = new OrderSessionKey(session.getId(), order.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public OrderSessionKey getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(OrderSessionKey id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Order getOrder() {
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrder(Order order) {
|
||||||
|
this.order = order;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Session getSession() {
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSession(Session session) {
|
||||||
|
this.session = session;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getCount() {
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCount(Integer count) {
|
||||||
|
this.count = count;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package com.labwork1.app.student.model;
|
||||||
|
|
||||||
|
import jakarta.persistence.Embeddable;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@Embeddable
|
||||||
|
public class OrderSessionKey implements Serializable {
|
||||||
|
private Long sessionId;
|
||||||
|
private Long orderId;
|
||||||
|
|
||||||
|
public OrderSessionKey() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public OrderSessionKey(Long sessionId, Long orderId) {
|
||||||
|
this.sessionId = sessionId;
|
||||||
|
this.orderId = orderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getSessionId() {
|
||||||
|
return sessionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSessionId(Long sessionId) {
|
||||||
|
this.sessionId = sessionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getOrderId() {
|
||||||
|
return orderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrderId(Long orderId) {
|
||||||
|
this.orderId = orderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof OrderSessionKey that)) return false;
|
||||||
|
return Objects.equals(getSessionId(), that.getSessionId()) && Objects.equals(getOrderId(), that.getOrderId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(getSessionId(), getOrderId());
|
||||||
|
}
|
||||||
|
}
|
160
src/main/java/com/labwork1/app/student/model/Session.java
Normal file
160
src/main/java/com/labwork1/app/student/model/Session.java
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
package com.labwork1.app.student.model;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class Session {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||||
|
protected Long id;
|
||||||
|
@NotNull(message = "price can't be null or empty")
|
||||||
|
protected Double price;
|
||||||
|
@NotNull(message = "dateTime can't be null or empty")
|
||||||
|
@Column(name = "date_time")
|
||||||
|
@Temporal(TemporalType.TIMESTAMP)
|
||||||
|
protected Timestamp dateTime;
|
||||||
|
@OneToMany(mappedBy = "session", fetch = FetchType.EAGER)
|
||||||
|
private List<OrderSession> orders;
|
||||||
|
@OneToMany(mappedBy = "session", fetch = FetchType.EAGER)
|
||||||
|
private List<UserSession> users;
|
||||||
|
@ManyToOne(fetch = FetchType.EAGER)
|
||||||
|
@JoinColumn(name = "cinema_fk")
|
||||||
|
protected Cinema cinema;
|
||||||
|
@NotNull(message = "maxCount can't be null or empty")
|
||||||
|
@Column(name = "max_count")
|
||||||
|
protected Integer maxCount;
|
||||||
|
|
||||||
|
public Session() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getMaxCount() {
|
||||||
|
return maxCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Session(Double price, Timestamp dateTime, Integer maxCount) {
|
||||||
|
this.price = price;
|
||||||
|
this.dateTime = dateTime;
|
||||||
|
this.maxCount = maxCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Session(Session session) {
|
||||||
|
this.id = session.getId();
|
||||||
|
this.price = session.getPrice();
|
||||||
|
this.dateTime = session.getTimestamp();
|
||||||
|
this.orders = session.getOrders();
|
||||||
|
this.users = session.getUsers();
|
||||||
|
this.cinema = session.getCinema();
|
||||||
|
this.maxCount = session.getMaxCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cinema getCinema() {
|
||||||
|
return cinema;
|
||||||
|
}
|
||||||
|
public void setCinema(Cinema cinema) {
|
||||||
|
this.cinema = cinema;
|
||||||
|
if (!cinema.getSessions().contains(this)) {
|
||||||
|
cinema.setSession(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void addOrder(OrderSession orderSession){
|
||||||
|
if (orders == null){
|
||||||
|
orders = new ArrayList<>();
|
||||||
|
}
|
||||||
|
if (!orders.contains(orderSession)) {
|
||||||
|
this.orders.add(orderSession);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeOrder(OrderSession orderSession){
|
||||||
|
if (orders.contains(orderSession))
|
||||||
|
this.orders.remove(orderSession);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addUser(UserSession userSession){
|
||||||
|
if (users == null){
|
||||||
|
users = new ArrayList<>();
|
||||||
|
}
|
||||||
|
if (!users.contains(userSession)) {
|
||||||
|
this.users.add(userSession);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeUser(UserSession userSession){
|
||||||
|
if (users.contains(userSession))
|
||||||
|
this.users.remove(userSession);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
Session session = (Session) o;
|
||||||
|
return Objects.equals(id, session.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Session {" +
|
||||||
|
"id=" + id +
|
||||||
|
", price='" + price + '\'' +
|
||||||
|
", dateTime='" + dateTime.toString() + '\'' +
|
||||||
|
", maxCount='" + maxCount.toString() + '\'' +
|
||||||
|
", cinema='" + cinema.toString() + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getPrice() {
|
||||||
|
return price;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrders(List<OrderSession> orders) {
|
||||||
|
this.orders = orders;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxCount(Integer maxCount) {
|
||||||
|
this.maxCount = maxCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrice(Double price) {
|
||||||
|
this.price = price;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Timestamp getTimestamp() {
|
||||||
|
return dateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTimestamp(Timestamp dateTime) {
|
||||||
|
this.dateTime = dateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<OrderSession> getOrders() {
|
||||||
|
return orders;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsers(List<UserSession> users) {
|
||||||
|
this.users = users;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<UserSession> getUsers() {
|
||||||
|
return users;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package com.labwork1.app.student.model;
|
||||||
|
|
||||||
|
public class SessionExtension extends Session {
|
||||||
|
private Long capacity;
|
||||||
|
public SessionExtension(Session session, Long capacity) {
|
||||||
|
super(session);
|
||||||
|
this.capacity = capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getCapacity() {
|
||||||
|
return capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCapacity(Long capacity) {
|
||||||
|
this.capacity = capacity;
|
||||||
|
}
|
||||||
|
}
|
127
src/main/java/com/labwork1/app/student/model/User.java
Normal file
127
src/main/java/com/labwork1/app/student/model/User.java
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
package com.labwork1.app.student.model;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.Size;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "tab_user")
|
||||||
|
public class User {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||||
|
private Long id;
|
||||||
|
@Column(nullable = false, unique = true, length = 64)
|
||||||
|
@NotBlank(message = "login can't be null or empty")
|
||||||
|
@Size(min = 3, max = 64)
|
||||||
|
private String login;
|
||||||
|
@Column(nullable = false, length = 64)
|
||||||
|
@NotBlank(message = "password can't be null or empty")
|
||||||
|
@Size(min = 6, max = 64)
|
||||||
|
private String password;
|
||||||
|
@OneToMany(fetch = FetchType.EAGER, mappedBy = "user", cascade = {CascadeType.MERGE,CascadeType.REMOVE})
|
||||||
|
private List<Order> orders;
|
||||||
|
@OneToMany(mappedBy = "user", fetch = FetchType.EAGER, cascade =
|
||||||
|
{
|
||||||
|
CascadeType.REMOVE,
|
||||||
|
CascadeType.MERGE,
|
||||||
|
CascadeType.PERSIST
|
||||||
|
}, orphanRemoval = true)
|
||||||
|
private List<UserSession> sessions;
|
||||||
|
private UserRole role;
|
||||||
|
|
||||||
|
public User() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public User(String login, String password) {
|
||||||
|
this.login = login;
|
||||||
|
this.password = password;
|
||||||
|
this.orders = new ArrayList<>();
|
||||||
|
this.sessions = new ArrayList<>();
|
||||||
|
this.role = UserRole.USER;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User(String login, String password, UserRole role) {
|
||||||
|
this.login = login;
|
||||||
|
this.password = password;
|
||||||
|
this.orders = new ArrayList<>();
|
||||||
|
this.sessions = new ArrayList<>();
|
||||||
|
this.role = role;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSession(UserSession userSession) {
|
||||||
|
if (sessions == null) {
|
||||||
|
sessions = new ArrayList<>();
|
||||||
|
}
|
||||||
|
if (!sessions.contains(userSession))
|
||||||
|
this.sessions.add(userSession);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeSession(UserSession userSession){
|
||||||
|
if (sessions.contains(userSession))
|
||||||
|
this.sessions.remove(userSession);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
User user = (User) o;
|
||||||
|
return Objects.equals(id, user.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "User {" +
|
||||||
|
"id=" + id +
|
||||||
|
", login='" + login + '\'' +
|
||||||
|
", password='" + password + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserRole getRole() {
|
||||||
|
return role;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLogin() {
|
||||||
|
return login;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLogin(String login) {
|
||||||
|
this.login = login;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Order> getOrders() {
|
||||||
|
return orders;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrder(Order order) {
|
||||||
|
if (order.getUser().equals(this)) {
|
||||||
|
this.orders.add(order);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<UserSession> getSessions() {
|
||||||
|
return sessions;
|
||||||
|
}
|
||||||
|
}
|
20
src/main/java/com/labwork1/app/student/model/UserRole.java
Normal file
20
src/main/java/com/labwork1/app/student/model/UserRole.java
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package com.labwork1.app.student.model;
|
||||||
|
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
|
||||||
|
public enum UserRole implements GrantedAuthority {
|
||||||
|
ADMIN,
|
||||||
|
USER;
|
||||||
|
|
||||||
|
private static final String PREFIX = "ROLE_";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAuthority() {
|
||||||
|
return PREFIX + this.name();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class AsString {
|
||||||
|
public static final String ADMIN = PREFIX + "ADMIN";
|
||||||
|
public static final String USER = PREFIX + "USER";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package com.labwork1.app.student.model;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "user_session")
|
||||||
|
public class UserSession {
|
||||||
|
@EmbeddedId
|
||||||
|
private UserSessionKey id;
|
||||||
|
@ManyToOne
|
||||||
|
@MapsId("sessionId")
|
||||||
|
@JoinColumn(name = "session_id")
|
||||||
|
private Session session;
|
||||||
|
@ManyToOne
|
||||||
|
@MapsId("userId")
|
||||||
|
@JoinColumn(name = "user_id")
|
||||||
|
private User user;
|
||||||
|
@Column(name = "count")
|
||||||
|
private Integer count;
|
||||||
|
|
||||||
|
public UserSession() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserSession(User user, Session session, Integer count) {
|
||||||
|
this.user = user;
|
||||||
|
this.session = session;
|
||||||
|
this.count = count;
|
||||||
|
this.id = new UserSessionKey(session.getId(), user.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserSessionKey getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(UserSessionKey id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUser(User user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Session getSession() {
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSession(Session session) {
|
||||||
|
this.session = session;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getCount() {
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCount(Integer count) {
|
||||||
|
this.count = count;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package com.labwork1.app.student.model;
|
||||||
|
|
||||||
|
import jakarta.persistence.Embeddable;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@Embeddable
|
||||||
|
public class UserSessionKey implements Serializable {
|
||||||
|
private Long sessionId;
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
public UserSessionKey() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserSessionKey(Long sessionId, Long userId) {
|
||||||
|
this.sessionId = sessionId;
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getSessionId() {
|
||||||
|
return sessionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSessionId(Long sessionId) {
|
||||||
|
this.sessionId = sessionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserId(Long userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof UserSessionKey that)) return false;
|
||||||
|
return Objects.equals(getSessionId(), that.getSessionId()) && Objects.equals(getUserId(), that.getUserId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(getSessionId(), getUserId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
|||||||
|
package com.labwork1.app.student.repository;
|
||||||
|
|
||||||
|
import com.labwork1.app.student.model.Cinema;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface CinemaRepository extends JpaRepository<Cinema, Long> {
|
||||||
|
@Query("select p from Cinema p where p.name like CONCAT('%',:search,'%')")
|
||||||
|
List<Cinema> findAll(@Param("search") String search);
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package com.labwork1.app.student.repository;
|
||||||
|
|
||||||
|
import com.labwork1.app.student.model.Order;
|
||||||
|
import com.labwork1.app.student.model.OrderSession;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
|
|
||||||
|
public interface OrderRepository extends JpaRepository<Order, Long> {
|
||||||
|
@Query("Select os from OrderSession os where os.order.id = :orderId and os.session.id = :sessionId")
|
||||||
|
OrderSession getOrderSession(@Param("orderId") Long orderId, @Param("sessionId") Long sessionId);
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package com.labwork1.app.student.repository;
|
||||||
|
|
||||||
|
import com.labwork1.app.student.model.Session;
|
||||||
|
import com.labwork1.app.student.model.SessionExtension;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public interface SessionRepository extends JpaRepository<Session, Long> {
|
||||||
|
@Query("Select sum(os.count) from OrderSession os where os.session.id = :sessionId")
|
||||||
|
Optional<Integer> getCapacity(@Param("sessionId") Long sessionId);
|
||||||
|
@Query("Select new com.labwork1.app.student.model.SessionExtension(s, sum(os.count)) from Session s " +
|
||||||
|
"left join OrderSession os on s.id = os.session.id " +
|
||||||
|
"group by s")
|
||||||
|
List<SessionExtension> getSessionsWithCapacity();
|
||||||
|
@Query("Select new com.labwork1.app.student.model.SessionExtension(s, sum(os.count)) from Session s " +
|
||||||
|
"left join OrderSession os on s.id = os.session.id " +
|
||||||
|
"where s.id = :sessionId " +
|
||||||
|
"group by s")
|
||||||
|
Optional<SessionExtension> getSessionWithCapacity(@Param("sessionId") Long sessionId);
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package com.labwork1.app.student.repository;
|
||||||
|
|
||||||
|
import com.labwork1.app.student.model.OrderSession;
|
||||||
|
import com.labwork1.app.student.model.User;
|
||||||
|
import com.labwork1.app.student.model.UserSession;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
|
|
||||||
|
public interface UserRepository extends JpaRepository<User, Long> {
|
||||||
|
User findOneByLoginIgnoreCase(String login);
|
||||||
|
@Query("Select us from UserSession us where us.user.id = :userId and us.session.id = :sessionId")
|
||||||
|
UserSession getUserSession(@Param("userId") Long userId, @Param("sessionId") Long sessionId);
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.labwork1.app.student.service;
|
||||||
|
|
||||||
|
public class CinemaNotFoundException extends RuntimeException {
|
||||||
|
public CinemaNotFoundException(Long id) {
|
||||||
|
super(String.format("Cinema with id [%s] is not found", id));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
package com.labwork1.app.student.service;
|
||||||
|
|
||||||
|
import com.labwork1.app.student.controller.CinemaDto;
|
||||||
|
import com.labwork1.app.student.model.Cinema;
|
||||||
|
import com.labwork1.app.student.repository.CinemaRepository;
|
||||||
|
import com.labwork1.app.util.validation.ValidatorUtil;
|
||||||
|
import jakarta.transaction.Transactional;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class CinemaService {
|
||||||
|
private final CinemaRepository cinemaRepository;
|
||||||
|
private final ValidatorUtil validatorUtil;
|
||||||
|
|
||||||
|
public CinemaService(CinemaRepository cinemaRepository, ValidatorUtil validatorUtil) {
|
||||||
|
this.cinemaRepository = cinemaRepository;
|
||||||
|
this.validatorUtil = validatorUtil;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Cinema addCinema(CinemaDto dto) {
|
||||||
|
final Cinema cinema = new Cinema(dto);
|
||||||
|
validatorUtil.validate(cinema);
|
||||||
|
return cinemaRepository.save(cinema);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Cinema findCinema(Long id) {
|
||||||
|
final Optional<Cinema> cinema = cinemaRepository.findById(id);
|
||||||
|
return cinema.orElseThrow(() -> new CinemaNotFoundException(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public List<Cinema> findAllCinemas(String search) {
|
||||||
|
return cinemaRepository.findAll(search);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public List<Cinema> findAllCinemas() {
|
||||||
|
return cinemaRepository.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Cinema updateCinema(CinemaDto cinema) {
|
||||||
|
final Cinema currentCinema = findCinema(cinema.getId());
|
||||||
|
currentCinema.setName(cinema.getName());
|
||||||
|
currentCinema.setImage(cinema.getImage().getBytes());
|
||||||
|
validatorUtil.validate(currentCinema);
|
||||||
|
return cinemaRepository.save(currentCinema);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Cinema deleteCinema(Long id) {
|
||||||
|
final Cinema currentCinema = findCinema(id);
|
||||||
|
cinemaRepository.delete(currentCinema);
|
||||||
|
return currentCinema;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void deleteAllCinemas() {
|
||||||
|
cinemaRepository.deleteAll();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.labwork1.app.student.service;
|
||||||
|
|
||||||
|
public class OrderNotFoundException extends RuntimeException {
|
||||||
|
public OrderNotFoundException(Long id) {
|
||||||
|
super(String.format("Order with id [%s] is not found", id));
|
||||||
|
}
|
||||||
|
}
|
112
src/main/java/com/labwork1/app/student/service/OrderService.java
Normal file
112
src/main/java/com/labwork1/app/student/service/OrderService.java
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
package com.labwork1.app.student.service;
|
||||||
|
|
||||||
|
import com.labwork1.app.student.model.*;
|
||||||
|
import com.labwork1.app.student.repository.OrderRepository;
|
||||||
|
import com.labwork1.app.util.validation.ValidatorUtil;
|
||||||
|
import jakarta.persistence.EntityNotFoundException;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.sql.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class OrderService {
|
||||||
|
private final OrderRepository orderRepository;
|
||||||
|
private final UserService userService;
|
||||||
|
private final SessionService sessionService;
|
||||||
|
private final ValidatorUtil validatorUtil;
|
||||||
|
|
||||||
|
public OrderService(OrderRepository orderRepository, UserService userService, SessionService sessionService, ValidatorUtil validatorUtil) {
|
||||||
|
this.orderRepository = orderRepository;
|
||||||
|
this.userService = userService;
|
||||||
|
this.sessionService = sessionService;
|
||||||
|
this.validatorUtil = validatorUtil;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Order addOrder(Long userId) {
|
||||||
|
final Order order = new Order();
|
||||||
|
final User user = userService.findUser(userId);
|
||||||
|
order.setUser(user);
|
||||||
|
validatorUtil.validate(order);
|
||||||
|
return orderRepository.save(order);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Order addOrder(String userName) {
|
||||||
|
final Order order = new Order();
|
||||||
|
final User user = userService.findByLogin(userName);
|
||||||
|
order.setUser(user);
|
||||||
|
validatorUtil.validate(order);
|
||||||
|
return orderRepository.save(order);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Order addSession(Long id, Long sessionId, Integer count) {
|
||||||
|
final Session currentSession = sessionService.findSession(sessionId);
|
||||||
|
final Order currentOrder = findOrder(id);
|
||||||
|
final OrderSession currentOrderSession = orderRepository.getOrderSession(id, sessionId);
|
||||||
|
|
||||||
|
final Integer currentSessionCapacity = currentSession.getMaxCount() - sessionService.getCapacity(sessionId);
|
||||||
|
if (currentSessionCapacity < count ||
|
||||||
|
(currentOrderSession != null && currentOrderSession.getCount() + count > currentSession.getMaxCount())) {
|
||||||
|
throw new IllegalArgumentException(String.format("No more tickets in session. Capacity: %1$s. Count: %2$s",
|
||||||
|
currentSessionCapacity, count));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentOrderSession == null) {
|
||||||
|
currentOrder.addSession(new OrderSession(currentOrder, currentSession, count));
|
||||||
|
}
|
||||||
|
else if (currentOrderSession.getCount() + count <= currentSession.getMaxCount()) {
|
||||||
|
currentOrder.removeSession(currentOrderSession);
|
||||||
|
currentOrder.addSession(new OrderSession(currentOrder, currentSession,
|
||||||
|
currentOrderSession.getCount() + count));
|
||||||
|
}
|
||||||
|
|
||||||
|
return orderRepository.save(currentOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public Order findOrder(Long id) {
|
||||||
|
final Optional<Order> order = orderRepository.findById(id);
|
||||||
|
return order.orElseThrow(() -> new OrderNotFoundException(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public List<Order> findAllOrders() {
|
||||||
|
return orderRepository.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Order deleteOrder(Long id) {
|
||||||
|
final Order currentOrder = findOrder(id);
|
||||||
|
orderRepository.delete(currentOrder);
|
||||||
|
return currentOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Order deleteSessionInOrder(Long id, Long session, Integer count) {
|
||||||
|
final Order currentOrder = findOrder(id);
|
||||||
|
final Session currentSession = sessionService.findSession(session);
|
||||||
|
final OrderSession currentOrderSession = orderRepository.getOrderSession(id, session);
|
||||||
|
if (currentOrderSession == null)
|
||||||
|
throw new EntityNotFoundException();
|
||||||
|
|
||||||
|
if (count >= currentOrderSession.getCount()) {
|
||||||
|
currentOrder.removeSession(currentOrderSession);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
currentOrder.removeSession(currentOrderSession);
|
||||||
|
currentOrder.addSession(new OrderSession(currentOrder, currentSession,
|
||||||
|
currentOrderSession.getCount() - count));
|
||||||
|
}
|
||||||
|
return orderRepository.save(currentOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void deleteAllOrders() {
|
||||||
|
orderRepository.deleteAll();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.labwork1.app.student.service;
|
||||||
|
|
||||||
|
public class SessionNotFoundException extends RuntimeException {
|
||||||
|
public SessionNotFoundException(Long id) {
|
||||||
|
super(String.format("Session with id [%s] is not found", id));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,81 @@
|
|||||||
|
package com.labwork1.app.student.service;
|
||||||
|
|
||||||
|
import com.labwork1.app.student.model.Cinema;
|
||||||
|
import com.labwork1.app.student.model.Session;
|
||||||
|
import com.labwork1.app.student.model.SessionExtension;
|
||||||
|
import com.labwork1.app.student.repository.SessionRepository;
|
||||||
|
import com.labwork1.app.util.validation.ValidatorUtil;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class SessionService {
|
||||||
|
private final SessionRepository sessionRepository;
|
||||||
|
private final CinemaService cinemaService;
|
||||||
|
private final ValidatorUtil validatorUtil;
|
||||||
|
public SessionService(SessionRepository sessionRepository,
|
||||||
|
CinemaService cinemaService, ValidatorUtil validatorUtil) {
|
||||||
|
this.sessionRepository = sessionRepository;
|
||||||
|
this.cinemaService = cinemaService;
|
||||||
|
this.validatorUtil = validatorUtil;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Session addSession(Double price, Timestamp date, Long cinemaId, Integer capacity) {
|
||||||
|
final Session session = new Session(price, date, capacity);
|
||||||
|
final Cinema cinema = cinemaService.findCinema(cinemaId);
|
||||||
|
session.setCinema(cinema);
|
||||||
|
validatorUtil.validate(session);
|
||||||
|
return sessionRepository.save(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public SessionExtension findSession(Long id) {
|
||||||
|
return sessionRepository.getSessionWithCapacity(id)
|
||||||
|
.orElseThrow(() -> new SessionNotFoundException(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public Session findBaseSession(Long id) {
|
||||||
|
final Optional<Session> session = sessionRepository.findById(id);
|
||||||
|
return session.orElseThrow(() -> new SessionNotFoundException(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public List<SessionExtension> findAllSessions() {
|
||||||
|
return sessionRepository.getSessionsWithCapacity();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Session updateSession(Long id, Double price) {
|
||||||
|
final Session currentSession = findBaseSession(id);
|
||||||
|
currentSession.setPrice(price);
|
||||||
|
validatorUtil.validate(currentSession);
|
||||||
|
return sessionRepository.save(currentSession);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Session deleteSession(Long id) {
|
||||||
|
final Session currentSession = findBaseSession(id);
|
||||||
|
// все равно сеанс не удалился бы, который участвует в заказах
|
||||||
|
// для отслеживания операции с ошибкой
|
||||||
|
if (currentSession.getOrders().size() > 0)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
sessionRepository.delete(currentSession);
|
||||||
|
return currentSession;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void deleteAllSessions() {
|
||||||
|
sessionRepository.deleteAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Integer getCapacity(Long sessionId) {
|
||||||
|
return sessionRepository.getCapacity(sessionId).orElse(0);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.labwork1.app.student.service;
|
||||||
|
|
||||||
|
public class UserExistsException extends RuntimeException {
|
||||||
|
public UserExistsException(String login) {
|
||||||
|
super(String.format("User '%s' already exists", login));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.labwork1.app.student.service;
|
||||||
|
|
||||||
|
public class UserNotFoundException extends RuntimeException {
|
||||||
|
public UserNotFoundException(Long id) {
|
||||||
|
super(String.format("User with id [%s] is not found", id));
|
||||||
|
}
|
||||||
|
public UserNotFoundException(String login) {
|
||||||
|
super(String.format("User with login [%s] is not found", login));
|
||||||
|
}
|
||||||
|
}
|
171
src/main/java/com/labwork1/app/student/service/UserService.java
Normal file
171
src/main/java/com/labwork1/app/student/service/UserService.java
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
package com.labwork1.app.student.service;
|
||||||
|
|
||||||
|
import com.labwork1.app.configuration.jwt.JwtProvider;
|
||||||
|
import com.labwork1.app.student.controller.UserDto;
|
||||||
|
import com.labwork1.app.student.model.*;
|
||||||
|
import com.labwork1.app.student.repository.UserRepository;
|
||||||
|
import com.labwork1.app.util.validation.ValidationException;
|
||||||
|
import com.labwork1.app.util.validation.ValidatorUtil;
|
||||||
|
import jakarta.persistence.EntityNotFoundException;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.PageRequest;
|
||||||
|
import org.springframework.data.domain.Sort;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import com.labwork1.app.configuration.jwt.JwtException;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class UserService implements UserDetailsService {
|
||||||
|
private final UserRepository userRepository;
|
||||||
|
private final SessionService sessionService;
|
||||||
|
private final PasswordEncoder passwordEncoder;
|
||||||
|
private final ValidatorUtil validatorUtil;
|
||||||
|
private final JwtProvider jwtProvider;
|
||||||
|
|
||||||
|
public UserService(UserRepository userRepository, SessionService sessionService, PasswordEncoder passwordEncoder, ValidatorUtil validatorUtil, JwtProvider jwtProvider) {
|
||||||
|
this.userRepository = userRepository;
|
||||||
|
this.sessionService = sessionService;
|
||||||
|
this.passwordEncoder = passwordEncoder;
|
||||||
|
this.validatorUtil = validatorUtil;
|
||||||
|
this.jwtProvider = jwtProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Page<User> findAllPages(int page, int size) {
|
||||||
|
return userRepository.findAll(PageRequest.of(page - 1, size, Sort.by("id").ascending()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public User findByLogin(String login) {
|
||||||
|
return userRepository.findOneByLoginIgnoreCase(login);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public User addUser(String login, String password, String passwordConfirm) {
|
||||||
|
return createUser(login, password, passwordConfirm, UserRole.USER);
|
||||||
|
}
|
||||||
|
|
||||||
|
public User createUser(String login, String password, String passwordConfirm, UserRole role) {
|
||||||
|
if (findByLogin(login) != null) {
|
||||||
|
throw new UserExistsException(login);
|
||||||
|
}
|
||||||
|
final User user = new User(login, passwordEncoder.encode(password), role);
|
||||||
|
validatorUtil.validate(user);
|
||||||
|
if (!Objects.equals(password, passwordConfirm)) {
|
||||||
|
throw new ValidationException("Passwords not equals");
|
||||||
|
}
|
||||||
|
return userRepository.save(user);
|
||||||
|
}
|
||||||
|
public String loginAndGetToken(UserDto userDto) {
|
||||||
|
final User user = findByLogin(userDto.getLogin());
|
||||||
|
if (user == null) {
|
||||||
|
throw new UserNotFoundException(userDto.getLogin());
|
||||||
|
}
|
||||||
|
if (!passwordEncoder.matches(userDto.getPassword(), user.getPassword())) {
|
||||||
|
throw new UserNotFoundException(user.getLogin());
|
||||||
|
}
|
||||||
|
return jwtProvider.generateToken(user.getLogin());
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserDetails loadUserByToken(String token) throws UsernameNotFoundException {
|
||||||
|
if (!jwtProvider.isTokenValid(token)) {
|
||||||
|
throw new JwtException("Bad token");
|
||||||
|
}
|
||||||
|
final String userLogin = jwtProvider.getLoginFromToken(token)
|
||||||
|
.orElseThrow(() -> new JwtException("Token is not contain Login"));
|
||||||
|
return loadUserByUsername(userLogin);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||||
|
final User userEntity = findByLogin(username);
|
||||||
|
if (userEntity == null) {
|
||||||
|
throw new UsernameNotFoundException(username);
|
||||||
|
}
|
||||||
|
return new org.springframework.security.core.userdetails.User(
|
||||||
|
userEntity.getLogin(), userEntity.getPassword(), Collections.singleton(userEntity.getRole()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public User findUser(Long id) {
|
||||||
|
final Optional<User> user = userRepository.findById(id);
|
||||||
|
return user.orElseThrow(() -> new UserNotFoundException(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public List<User> findAllUsers() {
|
||||||
|
return userRepository.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public User updateUser(Long id, String login, String password) {
|
||||||
|
final User currentUser = findUser(id);
|
||||||
|
currentUser.setLogin(login);
|
||||||
|
currentUser.setPassword(passwordEncoder.encode(password));
|
||||||
|
validatorUtil.validate(currentUser);
|
||||||
|
return userRepository.save(currentUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public User addSession(Long id, Long sessionId, Integer count) {
|
||||||
|
final Session currentSession = sessionService.findSession(sessionId);
|
||||||
|
final User currentUser = findUser(id);
|
||||||
|
final UserSession currentUserSession = userRepository.getUserSession(id, sessionId);
|
||||||
|
|
||||||
|
final Integer currentSessionCapacity = currentSession.getMaxCount() - sessionService.getCapacity(sessionId);
|
||||||
|
if (currentSessionCapacity < count ||
|
||||||
|
(currentUserSession != null && currentUserSession.getCount() + count > currentSession.getMaxCount())) {
|
||||||
|
throw new IllegalArgumentException(String.format("No more tickets in session. Capacity: %1$s. Count: %2$s",
|
||||||
|
currentSessionCapacity, count));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentUserSession == null) {
|
||||||
|
currentUser.addSession(new UserSession(currentUser, currentSession, count));
|
||||||
|
}
|
||||||
|
else if (currentUserSession.getCount() + count <= currentSession.getMaxCount()) {
|
||||||
|
currentUser.removeSession(currentUserSession);
|
||||||
|
currentUser.addSession(new UserSession(currentUser, currentSession,
|
||||||
|
currentUserSession.getCount() + count));
|
||||||
|
}
|
||||||
|
|
||||||
|
return userRepository.save(currentUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public User deleteSessionInCart(Long id, Long session, Integer count) {
|
||||||
|
final User currentUser = findUser(id);
|
||||||
|
final Session currentSession = sessionService.findSession(session);
|
||||||
|
final UserSession currentUserSession = userRepository.getUserSession(id, session);
|
||||||
|
if (currentUserSession == null)
|
||||||
|
throw new EntityNotFoundException();
|
||||||
|
|
||||||
|
if (count >= currentUserSession.getCount()) {
|
||||||
|
currentUser.removeSession(currentUserSession);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
currentUser.removeSession(currentUserSession);
|
||||||
|
currentUser.addSession(new UserSession(currentUser, currentSession,
|
||||||
|
currentUserSession.getCount() - count));
|
||||||
|
}
|
||||||
|
return userRepository.save(currentUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public User deleteUser(Long id) {
|
||||||
|
final User user = findUser(id);
|
||||||
|
userRepository.deleteById(id);
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void deleteAllUsers() {
|
||||||
|
userRepository.deleteAll();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
package com.labwork1.app.util.error;
|
||||||
|
|
||||||
|
import com.labwork1.app.student.service.CinemaNotFoundException;
|
||||||
|
import com.labwork1.app.student.service.UserNotFoundException;
|
||||||
|
import com.labwork1.app.student.service.OrderNotFoundException;
|
||||||
|
import com.labwork1.app.student.service.SessionNotFoundException;
|
||||||
|
import com.labwork1.app.util.validation.ValidationException;
|
||||||
|
import org.springframework.context.support.DefaultMessageSourceResolvable;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||||
|
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||||
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
|
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@ControllerAdvice
|
||||||
|
public class AdviceController {
|
||||||
|
@ExceptionHandler({
|
||||||
|
UserNotFoundException.class,
|
||||||
|
OrderNotFoundException.class,
|
||||||
|
SessionNotFoundException.class,
|
||||||
|
CinemaNotFoundException.class,
|
||||||
|
ValidationException.class,
|
||||||
|
IllegalArgumentException.class
|
||||||
|
})
|
||||||
|
public ResponseEntity<Object> handleException(Throwable e) {
|
||||||
|
return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||||
|
public ResponseEntity<Object> handleBindException(MethodArgumentNotValidException e) {
|
||||||
|
final ValidationException validationException = new ValidationException(
|
||||||
|
e.getBindingResult().getAllErrors().stream()
|
||||||
|
.map(DefaultMessageSourceResolvable::getDefaultMessage)
|
||||||
|
.collect(Collectors.toSet()));
|
||||||
|
return handleException(validationException);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(Exception.class)
|
||||||
|
public ResponseEntity<Object> handleUnknownException(Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package com.labwork1.app.util.validation;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class ValidationException extends RuntimeException {
|
||||||
|
public ValidationException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValidationException(Set<String> errors) {
|
||||||
|
super(String.join("\n", errors));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package com.labwork1.app.util.validation;
|
||||||
|
|
||||||
|
import jakarta.validation.ConstraintViolation;
|
||||||
|
import jakarta.validation.Validation;
|
||||||
|
import jakarta.validation.Validator;
|
||||||
|
import jakarta.validation.ValidatorFactory;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class ValidatorUtil {
|
||||||
|
private final Validator validator;
|
||||||
|
|
||||||
|
public ValidatorUtil() {
|
||||||
|
try (ValidatorFactory factory = Validation.buildDefaultValidatorFactory()) {
|
||||||
|
this.validator = factory.getValidator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> void validate(T object) {
|
||||||
|
final Set<ConstraintViolation<T>> errors = validator.validate(object);
|
||||||
|
if (!errors.isEmpty()) {
|
||||||
|
throw new ValidationException(errors.stream()
|
||||||
|
.map(ConstraintViolation::getMessage)
|
||||||
|
.collect(Collectors.toSet()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1 +1,12 @@
|
|||||||
|
spring.main.banner-mode=off
|
||||||
|
spring.datasource.url=jdbc:h2:file:./data
|
||||||
|
spring.datasource.driverClassName=org.h2.Driver
|
||||||
|
spring.datasource.username=sa
|
||||||
|
spring.datasource.password=password
|
||||||
|
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
|
||||||
|
spring.jpa.hibernate.ddl-auto=update
|
||||||
|
spring.h2.console.enabled=true
|
||||||
|
spring.h2.console.settings.trace=false
|
||||||
|
spring.h2.console.settings.web-allow-others=false
|
||||||
|
jwt.dev-token=my-secret-jwt
|
||||||
|
jwt.dev=true
|
@ -1,13 +0,0 @@
|
|||||||
package com.labwork1.app;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
|
|
||||||
@SpringBootTest
|
|
||||||
class AppApplicationTests {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void contextLoads() {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
129
src/test/java/com/labwork1/app/JpaCustomerTests.java
Normal file
129
src/test/java/com/labwork1/app/JpaCustomerTests.java
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
//package com.labwork1.app;
|
||||||
|
//
|
||||||
|
//import com.labwork1.app.student.model.*;
|
||||||
|
//import com.labwork1.app.student.service.*;
|
||||||
|
//import org.junit.jupiter.api.Assertions;
|
||||||
|
//import org.junit.jupiter.api.Test;
|
||||||
|
//import org.slf4j.Logger;
|
||||||
|
//import org.slf4j.LoggerFactory;
|
||||||
|
//import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
//import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
//
|
||||||
|
//import java.sql.Timestamp;
|
||||||
|
//import java.util.List;
|
||||||
|
//
|
||||||
|
//@SpringBootTest
|
||||||
|
//public class JpaUserTests {
|
||||||
|
// private static final Logger log = LoggerFactory.getLogger(JpaUserTests.class);
|
||||||
|
// @Autowired
|
||||||
|
// private UserService userService;
|
||||||
|
// @Autowired
|
||||||
|
// private SessionService sessionService;
|
||||||
|
// @Autowired
|
||||||
|
// private OrderService orderService;
|
||||||
|
// @Autowired
|
||||||
|
// private CinemaService cinemaService;
|
||||||
|
//
|
||||||
|
// @Test
|
||||||
|
// void testOrder() {
|
||||||
|
// sessionService.deleteAllSessions();
|
||||||
|
// cinemaService.deleteAllCinemas();
|
||||||
|
// orderService.deleteAllOrders();
|
||||||
|
// userService.deleteAllUsers();
|
||||||
|
// // 2 кино
|
||||||
|
// final Cinema cinema1 = cinemaService.addCinema("Меню");
|
||||||
|
// final Cinema cinema2 = cinemaService.addCinema("Аватар");
|
||||||
|
//
|
||||||
|
// // 2 сеанса
|
||||||
|
// final Session session1 = sessionService.addSession(300.0,
|
||||||
|
// new Timestamp(System.currentTimeMillis()), cinema1.getId(), 10);
|
||||||
|
// final Session session2 = sessionService.addSession( 200.0,
|
||||||
|
// new Timestamp(System.currentTimeMillis()), cinema1.getId(), 10);
|
||||||
|
//
|
||||||
|
// // проверка 2 сеанса у 1 кино
|
||||||
|
// Assertions.assertEquals(cinemaService
|
||||||
|
// .findCinema(cinema1.getId()).getSessions().size(), 2);
|
||||||
|
// // 1 покупатель
|
||||||
|
// final User user1 = userService.addUser("Родион", "Иванов");
|
||||||
|
// userService.updateUser(user1.getId(), "Пчел", "Пчелов");
|
||||||
|
// Assertions.assertEquals(userService.findUser(user1.getId()).getLogin(), "Пчел");
|
||||||
|
// // 1 заказ, 1 копия заказа
|
||||||
|
// final Order order0 = orderService.addOrder(userService.findUser(user1.getId()).getId());
|
||||||
|
// final Order order1 = orderService.findOrder(order0.getId());
|
||||||
|
// Assertions.assertEquals(order0, order1);
|
||||||
|
//
|
||||||
|
// // у клиента точно есть заказ?
|
||||||
|
// Assertions.assertEquals(userService
|
||||||
|
// .findUser(user1.getId()).getOrders().size(), 1);
|
||||||
|
// // 0 заказов
|
||||||
|
// orderService.deleteAllOrders();
|
||||||
|
// Assertions.assertThrows(OrderNotFoundException.class, () -> orderService.findOrder(-1L));
|
||||||
|
// // 2 покупателя
|
||||||
|
// final User user2 = userService.addUser("Иннокентий", "Иванов");
|
||||||
|
//
|
||||||
|
// // 1 заказ
|
||||||
|
// final Order order2 = orderService
|
||||||
|
// .addOrder(userService.findUser(user2.getId()).getId());
|
||||||
|
// // у заказа 2 сеанса
|
||||||
|
// orderService.addSession(order2.getId(), session1.getId(), 2);
|
||||||
|
//
|
||||||
|
// List<SessionExtension> result = sessionService.findAllSessions();
|
||||||
|
//
|
||||||
|
// Assertions.assertEquals(sessionService.getCapacity(session1.getId()), 2);
|
||||||
|
//
|
||||||
|
// orderService.addSession(order2.getId(), session2.getId(), 5);
|
||||||
|
// Assertions.assertEquals(sessionService.getCapacity(session2.getId()), 5);
|
||||||
|
//
|
||||||
|
// Assertions.assertThrows(IllegalArgumentException.class, () ->
|
||||||
|
// orderService.addSession(order2.getId(), session2.getId(), 6));
|
||||||
|
//
|
||||||
|
// // у заказа 1 сеанс
|
||||||
|
// orderService.deleteSessionInOrder(order2.getId(), session2.getId(), 10);
|
||||||
|
// Assertions.assertEquals(sessionService.getCapacity(session2.getId()), 0);
|
||||||
|
// // заполнили всю 2 сессию
|
||||||
|
// orderService.addSession(order2.getId(), session2.getId(), 10);
|
||||||
|
//
|
||||||
|
// Assertions.assertEquals(sessionService.findAllSessions().size(), 2);
|
||||||
|
//
|
||||||
|
// orderService.deleteSessionInOrder(order2.getId(), session2.getId(), 4);
|
||||||
|
// Assertions.assertEquals(sessionService.getCapacity(session2.getId()), 6);
|
||||||
|
// orderService.deleteSessionInOrder(order2.getId(), session2.getId(), 6);
|
||||||
|
// Assertions.assertEquals(sessionService.getCapacity(session2.getId()), 0);
|
||||||
|
//
|
||||||
|
// Assertions.assertEquals(orderService.findOrder(order2.getId()).getSessions().size(), 1);
|
||||||
|
// Assertions.assertEquals(orderService.findOrder(order2.getId()).getSessions().get(0).getId().getSessionId(), session1.getId());
|
||||||
|
//
|
||||||
|
// // у заказа 1 сеанс
|
||||||
|
// // 3 сеанса всего
|
||||||
|
// final Session session3 = sessionService.addSession(300.0,
|
||||||
|
// new Timestamp(System.currentTimeMillis()), cinema2.getId(), 10);
|
||||||
|
// // удалили заказ2, у которого был сеанс1
|
||||||
|
// orderService.deleteOrder(order2.getId());
|
||||||
|
// Assertions.assertEquals(orderService.findAllOrders().size(), 0);
|
||||||
|
// Assertions.assertEquals(sessionService.findAllSessions().size(), 3);
|
||||||
|
//
|
||||||
|
// // создали 3 заказ у 2 покупателя
|
||||||
|
// final Order order3 = orderService
|
||||||
|
// .addOrder(userService.findUser(user2.getId()).getId());
|
||||||
|
// orderService.addSession(order3.getId(), session2.getId(), 2);
|
||||||
|
// orderService.addSession(order3.getId(), session3.getId(), 8);
|
||||||
|
// orderService.addSession(order3.getId(), session1.getId(), 8);
|
||||||
|
// // 2-ой покупатель удален
|
||||||
|
// // 0 заказов после его удаления
|
||||||
|
// Assertions.assertEquals(sessionService.getCapacity(session2.getId()), 2);
|
||||||
|
// userService.deleteUser(user2.getId());
|
||||||
|
//
|
||||||
|
// Assertions.assertThrows(UserNotFoundException.class, () -> userService.findUser(user2.getId()));
|
||||||
|
// Assertions.assertThrows(OrderNotFoundException.class, () -> orderService.findOrder(order3.getId()));
|
||||||
|
// Assertions.assertEquals(orderService.findAllOrders().size(), 0);
|
||||||
|
// Assertions.assertEquals(sessionService.getCapacity(session2.getId()), 0);
|
||||||
|
// Assertions.assertEquals(sessionService.getCapacity(session3.getId()), 0);
|
||||||
|
//
|
||||||
|
// Assertions.assertEquals(cinemaService.findAllCinemas().size(), 2);
|
||||||
|
// Assertions.assertEquals(sessionService.findAllSessions().size(), 3);
|
||||||
|
// // у синема1 1 и 2 сеанс, у синема2 3 сеанс. он удален
|
||||||
|
// cinemaService.deleteCinema(cinema2.getId());
|
||||||
|
// Assertions.assertEquals(cinemaService.findAllCinemas().size(), 1);
|
||||||
|
// Assertions.assertEquals(sessionService.findAllSessions().size(), 2);
|
||||||
|
// }
|
||||||
|
//}
|
6
src/test/resources/application.properties
Normal file
6
src/test/resources/application.properties
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
spring.datasource.url=jdbc:h2:mem:testdb
|
||||||
|
spring.datasource.driverClassName=org.h2.Driver
|
||||||
|
spring.datasource.username=sa
|
||||||
|
spring.datasource.password=password
|
||||||
|
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
|
||||||
|
spring.jpa.hibernate.ddl-auto=create-drop
|
Loading…
Reference in New Issue
Block a user