From c9e9f0fcb6f56cfa379a875f131c3fef4945da2a Mon Sep 17 00:00:00 2001 From: Jordan Date: Mon, 5 Mar 2018 12:06:39 +0000 Subject: [PATCH] Added Play Files --- .../controllers/$model__Camel$Controller.java | 43 + .../app/controllers/$model__Camel$Data.java | 37 + .../app/views/$model__camel$/form.scala.html | 12 + .g8/form/default.properties | 2 + .g8/form/generated-test/README.md | 1 + .../$model__Camel$ControllerTest.java | 50 + .gradle/4.4/fileChanges/last-build.bin | Bin 0 -> 1 bytes .gradle/4.4/fileHashes/fileHashes.bin | Bin 0 -> 18547 bytes .gradle/4.4/fileHashes/fileHashes.lock | Bin 0 -> 17 bytes .project | 17 + .settings/org.eclipse.buildship.core.prefs | 2 + .vscode/settings.json | 3 + app/controllers/AdminProductCtrl.java | 270 + app/controllers/ProductCtrl.java | 83 + app/controllers/security/CheckIfAdmin.java | 38 + app/controllers/security/CheckIfCustomer.java | 38 + app/controllers/security/LoginCtrl.java | 68 + app/controllers/security/Secured.java | 20 + app/models/products/Category.java | 77 + app/models/products/Product.java | 105 + app/models/users/Administrator.java | 26 + app/models/users/Customer.java | 75 + app/models/users/Login.java | 33 + app/models/users/Manager.java | 36 + app/models/users/User.java | 97 + app/views/listProducts.scala.html | 72 + app/views/login.scala.html | 38 + app/views/main.scala.html | 72 + app/views/productAdmin/addProduct.scala.html | 39 + .../productAdmin/listProducts.scala.html | 80 + app/views/productAdmin/main.scala.html | 75 + .../productAdmin/updateProduct.scala.html | 42 + app/views/productDetails.scala.html | 42 + build.gradle | 41 + build.sbt | 16 + conf/application.conf | 24 + conf/evolutions/default/1.sql | 63 + conf/evolutions/default/2.sql | 44 + conf/evolutions/default/3.sql | 8 + conf/logback.xml | 41 + conf/routes | 33 + data/productsDB.mv.db | Bin 0 -> 61440 bytes data/productsDB.trace.db | 68 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54329 bytes gradle/wrapper/gradle-wrapper.properties | 5 + gradlew | 172 + gradlew.bat | 84 + lib/im4java-1.4.0-1.5.jar | Bin 0 -> 155571 bytes logs/application.log | 108 + project/build.properties | 1 + project/plugins.sbt | 3 + .../$3f5b9005ed72c01f76f6$.class | Bin 0 -> 1620 bytes .../$3f5b9005ed72c01f76f6.cache | 1 + .../$3f5b9005ed72c01f76f6.class | Bin 0 -> 637 bytes .../$5d5834882062acfd1e5b$.class | Bin 0 -> 1622 bytes .../$5d5834882062acfd1e5b.cache | 1 + .../$5d5834882062acfd1e5b.class | Bin 0 -> 637 bytes project/scaffold.sbt | 6 + .../$15edceac93bbbc2d0ec9$.class | Bin 0 -> 2337 bytes .../$15edceac93bbbc2d0ec9.cache | 1 + .../$15edceac93bbbc2d0ec9.class | Bin 0 -> 627 bytes .../$367aab8432d8362236c3$.class | Bin 0 -> 2348 bytes .../$367aab8432d8362236c3.cache | 1 + .../$367aab8432d8362236c3.class | Bin 0 -> 627 bytes .../$379f864cd7690c0ed3b6$.class | Bin 0 -> 2352 bytes .../$379f864cd7690c0ed3b6.cache | 1 + .../$379f864cd7690c0ed3b6.class | Bin 0 -> 627 bytes .../$4cfd96b442a0e386d0aa$.class | Bin 0 -> 3182 bytes .../$4cfd96b442a0e386d0aa.cache | 1 + .../$4cfd96b442a0e386d0aa.class | Bin 0 -> 627 bytes .../$64c185fa21f6207ce868$.class | Bin 0 -> 3197 bytes .../$64c185fa21f6207ce868.cache | 1 + .../$64c185fa21f6207ce868.class | Bin 0 -> 627 bytes .../$66b18781b0dc04725c19$.class | Bin 0 -> 1545 bytes .../$66b18781b0dc04725c19.cache | 1 + .../$66b18781b0dc04725c19.class | Bin 0 -> 573 bytes .../$83d00abc169193955584$.class | Bin 0 -> 2738 bytes .../$83d00abc169193955584.cache | 1 + .../$83d00abc169193955584.class | Bin 0 -> 627 bytes .../$baf5680579e409f4dde1$.class | Bin 0 -> 2348 bytes .../$baf5680579e409f4dde1.cache | 1 + .../$baf5680579e409f4dde1.class | Bin 0 -> 627 bytes .../0.1-SNAPSHOT/resolved.xml.properties | 7 + .../sbt_1.0/0.1-SNAPSHOT/resolved.xml.xml | 40 + .../0.1-SNAPSHOT/resolved.xml.properties | 7 + .../sbt_1.0/0.1-SNAPSHOT/resolved.xml.xml | 40 + .../0.1-SNAPSHOT/resolved.xml.properties | 7 + .../sbt_1.0/0.1-SNAPSHOT/resolved.xml.xml | 40 + .../0.1-SNAPSHOT/resolved.xml.properties | 7 + .../sbt_1.0/0.1-SNAPSHOT/resolved.xml.xml | 40 + .../0.1-SNAPSHOT/resolved.xml.properties | 7 + .../sbt_1.0/0.1-SNAPSHOT/resolved.xml.xml | 40 + .../0.1-SNAPSHOT/resolved.xml.properties | 7 + .../sbt_1.0/0.1-SNAPSHOT/resolved.xml.xml | 40 + ...dauthentication-build-compile-internal.xml | 3101 ++ ...fault-crudauthentication-build-compile.xml | 2144 + ...ault-crudauthentication-build-optional.xml | 15 + ...efault-crudauthentication-build-plugin.xml | 15 + .../default-crudauthentication-build-pom.xml | 15 + ...ault-crudauthentication-build-provided.xml | 1057 + ...dauthentication-build-runtime-internal.xml | 2145 + ...fault-crudauthentication-build-runtime.xml | 2143 + ...lt-crudauthentication-build-scala-tool.xml | 78 + ...crudauthentication-build-test-internal.xml | 3096 ++ .../default-crudauthentication-build-test.xml | 2143 + ...lab1imageupload-build-compile-internal.xml | 3101 ++ .../default-lab1imageupload-build-compile.xml | 2144 + ...default-lab1imageupload-build-optional.xml | 15 + .../default-lab1imageupload-build-plugin.xml | 15 + .../default-lab1imageupload-build-pom.xml | 15 + ...default-lab1imageupload-build-provided.xml | 1057 + ...lab1imageupload-build-runtime-internal.xml | 2145 + .../default-lab1imageupload-build-runtime.xml | 2143 + ...fault-lab1imageupload-build-scala-tool.xml | 78 + ...lt-lab1imageupload-build-test-internal.xml | 3096 ++ .../default-lab1imageupload-build-test.xml | 2143 + ...lt-lab2skeleton-build-compile-internal.xml | 3109 ++ .../default-lab2skeleton-build-compile.xml | 2145 + .../default-lab2skeleton-build-optional.xml | 15 + .../default-lab2skeleton-build-plugin.xml | 15 + .../default-lab2skeleton-build-pom.xml | 15 + .../default-lab2skeleton-build-provided.xml | 1065 + ...lt-lab2skeleton-build-runtime-internal.xml | 2146 + .../default-lab2skeleton-build-runtime.xml | 2144 + .../default-lab2skeleton-build-scala-tool.xml | 78 + ...fault-lab2skeleton-build-test-internal.xml | 3104 ++ .../default-lab2skeleton-build-test.xml | 2144 + .../default-lab3-build-compile-internal.xml | 3109 ++ .../reports/default-lab3-build-compile.xml | 2145 + .../reports/default-lab3-build-optional.xml | 15 + .../reports/default-lab3-build-plugin.xml | 15 + .../reports/default-lab3-build-pom.xml | 15 + .../reports/default-lab3-build-provided.xml | 1065 + .../default-lab3-build-runtime-internal.xml | 2146 + .../reports/default-lab3-build-runtime.xml | 2144 + .../reports/default-lab3-build-scala-tool.xml | 78 + .../default-lab3-build-test-internal.xml | 3104 ++ .../reports/default-lab3-build-test.xml | 2144 + ...lt-lab3solution-build-compile-internal.xml | 3109 ++ .../default-lab3solution-build-compile.xml | 2145 + .../default-lab3solution-build-optional.xml | 15 + .../default-lab3solution-build-plugin.xml | 15 + .../default-lab3solution-build-pom.xml | 15 + .../default-lab3solution-build-provided.xml | 1065 + ...lt-lab3solution-build-runtime-internal.xml | 2146 + .../default-lab3solution-build-runtime.xml | 2144 + .../default-lab3solution-build-scala-tool.xml | 78 + ...fault-lab3solution-build-test-internal.xml | 3104 ++ .../default-lab3solution-build-test.xml | 2144 + ...lt-lab4skeleton-build-compile-internal.xml | 3109 ++ .../default-lab4skeleton-build-compile.xml | 2145 + .../default-lab4skeleton-build-optional.xml | 15 + .../default-lab4skeleton-build-plugin.xml | 15 + .../default-lab4skeleton-build-pom.xml | 15 + .../default-lab4skeleton-build-provided.xml | 1065 + ...lt-lab4skeleton-build-runtime-internal.xml | 2146 + .../default-lab4skeleton-build-runtime.xml | 2144 + .../default-lab4skeleton-build-scala-tool.xml | 78 + ...fault-lab4skeleton-build-test-internal.xml | 3104 ++ .../default-lab4skeleton-build-test.xml | 2144 + .../resolution-cache/reports/ivy-report.css | 279 + .../resolution-cache/reports/ivy-report.xsl | 514 + .../$global/$global/$global/streams/out | 0 .../streams/update_cache_2.12/input_dsp | 1 + .../streams/update_cache_2.12/output_dsp | 1 + .../ivyConfiguration/$global/streams/out | 3 + .../$global/ivySbt/$global/streams/out | 0 .../projectDescriptors/$global/streams/out | 0 .../$global/update/$global/streams/out | 37592 ++++++++++++++++ .../$global/streams/update_cache_2.12/inputs | 1 + .../$global/streams/update_cache_2.12/output | 1 + .../$global/discoveredMainClasses/data | 1 + .../compile/compile/$global/streams/out | 0 .../compileIncremental/$global/streams/export | 0 .../compileIncremental/$global/streams/out | 1 + .../$global/streams/copy-resources | 1 + .../compile/copyResources/$global/streams/out | 2 + .../$global/streams/export | 1 + .../exportedProducts/$global/streams/export | 1 + .../$global/streams/export | 1 + .../$global/streams/export | 1 + .../managedClasspath/$global/streams/export | 1 + .../unmanagedClasspath/$global/streams/export | 1 + .../unmanagedJars/$global/streams/export | 1 + .../$global/streams/export | 1 + .../exportedProducts/$global/streams/export | 1 + .../$global/streams/export | 1 + .../fullClasspath/$global/streams/export | 1 + .../$global/streams/export | 1 + .../managedClasspath/$global/streams/export | 1 + .../unmanagedClasspath/$global/streams/export | 1 + .../unmanagedJars/$global/streams/export | 1 + public/images/favicon.png | Bin 0 -> 687 bytes public/images/productImages/1.jpg | Bin 0 -> 6149 bytes public/images/productImages/10.jpg | Bin 0 -> 22509 bytes public/images/productImages/11.jpg | Bin 0 -> 7106 bytes public/images/productImages/12.jpg | Bin 0 -> 4241 bytes public/images/productImages/13.jpg | Bin 0 -> 11680 bytes public/images/productImages/14.jpg | Bin 0 -> 11680 bytes public/images/productImages/14.png | Bin 0 -> 4332 bytes public/images/productImages/15.jpg | Bin 0 -> 11680 bytes public/images/productImages/2.jpg | Bin 0 -> 24319 bytes public/images/productImages/3.jpg | Bin 0 -> 8693 bytes public/images/productImages/4.jpg | Bin 0 -> 7415 bytes public/images/productImages/45.jpg | Bin 0 -> 10903 bytes public/images/productImages/46.jpg | Bin 0 -> 10903 bytes public/images/productImages/6.jpg | Bin 0 -> 22264 bytes public/images/productImages/7.jpg | Bin 0 -> 22009 bytes public/images/productImages/8.jpg | Bin 0 -> 10567 bytes public/images/productImages/9.jpg | Bin 0 -> 4261 bytes public/images/productImages/thumbnails/1.jpg | Bin 0 -> 1810 bytes public/images/productImages/thumbnails/10.jpg | Bin 0 -> 6275 bytes public/images/productImages/thumbnails/11.jpg | Bin 0 -> 953 bytes public/images/productImages/thumbnails/12.jpg | Bin 0 -> 1746 bytes public/images/productImages/thumbnails/13.jpg | Bin 0 -> 3121 bytes public/images/productImages/thumbnails/14.jpg | Bin 0 -> 3121 bytes public/images/productImages/thumbnails/15.jpg | Bin 0 -> 3121 bytes public/images/productImages/thumbnails/2.jpg | Bin 0 -> 4968 bytes public/images/productImages/thumbnails/3.jpg | Bin 0 -> 1664 bytes public/images/productImages/thumbnails/4.jpg | Bin 0 -> 952 bytes public/images/productImages/thumbnails/45.jpg | Bin 0 -> 1160 bytes public/images/productImages/thumbnails/46.jpg | Bin 0 -> 1160 bytes public/images/productImages/thumbnails/6.jpg | Bin 0 -> 1964 bytes public/images/productImages/thumbnails/7.jpg | Bin 0 -> 2940 bytes public/images/productImages/thumbnails/8.jpg | Bin 0 -> 2050 bytes public/images/productImages/thumbnails/9.jpg | Bin 0 -> 824 bytes .../productImages/thumbnails/noImage.jpg | Bin 0 -> 1647 bytes public/javascripts/main.js | 3 + public/stylesheets/main.css | 3 + target/.history | 258 + target/scala-2.12/classes/application.conf | 24 + .../controllers/AdminProductCtrl.class | Bin 0 -> 8992 bytes .../classes/controllers/ProductCtrl.class | Bin 0 -> 2701 bytes .../controllers/ReverseAdminProductCtrl.class | Bin 0 -> 4720 bytes .../classes/controllers/ReverseAssets.class | Bin 0 -> 3668 bytes .../controllers/ReverseProductCtrl.class | Bin 0 -> 3944 bytes .../classes/controllers/Secured.class | Bin 0 -> 1151 bytes .../javascript/ReverseAdminProductCtrl.class | Bin 0 -> 4741 bytes .../javascript/ReverseAssets.class | Bin 0 -> 2703 bytes .../javascript/ReverseProductCtrl.class | Bin 0 -> 3343 bytes .../controllers/routes$javascript.class | Bin 0 -> 944 bytes .../classes/controllers/routes.class | Bin 0 -> 867 bytes .../controllers/security/CheckIfAdmin.class | Bin 0 -> 1900 bytes .../security/CheckIfCustomer.class | Bin 0 -> 1906 bytes .../controllers/security/LoginCtrl.class | Bin 0 -> 2723 bytes .../security/ReverseLoginCtrl.class | Bin 0 -> 2195 bytes .../javascript/ReverseLoginCtrl.class | Bin 0 -> 2616 bytes .../security/routes$javascript.class | Bin 0 -> 689 bytes .../classes/controllers/security/routes.class | Bin 0 -> 656 bytes .../classes/evolutions/default/1.sql | 63 + .../classes/evolutions/default/2.sql | 44 + .../classes/evolutions/default/3.sql | 8 + target/scala-2.12/classes/logback.xml | 41 + .../classes/models/products/Category.class | Bin 0 -> 9213 bytes .../classes/models/products/Product.class | Bin 0 -> 11246 bytes .../classes/models/users/Administrator.class | Bin 0 -> 3313 bytes .../classes/models/users/Customer.class | Bin 0 -> 7611 bytes .../classes/models/users/Login.class | Bin 0 -> 970 bytes .../classes/models/users/Manager.class | Bin 0 -> 4543 bytes .../classes/models/users/User.class | Bin 0 -> 8758 bytes .../router/Routes$$anonfun$routes$1.class | Bin 0 -> 17203 bytes target/scala-2.12/classes/router/Routes.class | Bin 0 -> 34270 bytes .../classes/router/RoutesPrefix$.class | Bin 0 -> 2221 bytes .../classes/router/RoutesPrefix.class | Bin 0 -> 1097 bytes target/scala-2.12/classes/routes | 33 + .../classes/views/html/listProducts$.class | Bin 0 -> 10271 bytes .../classes/views/html/listProducts.class | Bin 0 -> 3695 bytes .../classes/views/html/login$.class | Bin 0 -> 8764 bytes .../scala-2.12/classes/views/html/login.class | Bin 0 -> 3332 bytes .../scala-2.12/classes/views/html/main$.class | Bin 0 -> 7988 bytes .../scala-2.12/classes/views/html/main.class | Bin 0 -> 3308 bytes .../views/html/productAdmin/addProduct$.class | Bin 0 -> 10407 bytes .../views/html/productAdmin/addProduct.class | Bin 0 -> 3475 bytes .../html/productAdmin/listProducts$.class | Bin 0 -> 11188 bytes .../html/productAdmin/listProducts.class | Bin 0 -> 3767 bytes .../views/html/productAdmin/main$.class | Bin 0 -> 8130 bytes .../views/html/productAdmin/main.class | Bin 0 -> 3381 bytes .../html/productAdmin/updateProduct$.class | Bin 0 -> 11302 bytes .../html/productAdmin/updateProduct.class | Bin 0 -> 3595 bytes .../classes/views/html/productDetails$.class | Bin 0 -> 6558 bytes .../classes/views/html/productDetails.class | Bin 0 -> 3379 bytes .../1.0-SNAPSHOT/resolved.xml.properties | 18 + .../lab3_2.12/1.0-SNAPSHOT/resolved.xml.xml | 59 + ...com.example-lab3_2.12-compile-internal.xml | 1298 + .../reports/com.example-lab3_2.12-compile.xml | 1521 + .../reports/com.example-lab3_2.12-debian.xml | 13 + .../reports/com.example-lab3_2.12-docker.xml | 13 + .../reports/com.example-lab3_2.12-docs.xml | 794 + .../reports/com.example-lab3_2.12-linux.xml | 13 + .../com.example-lab3_2.12-optional.xml | 13 + .../reports/com.example-lab3_2.12-plugin.xml | 13 + .../reports/com.example-lab3_2.12-pom.xml | 13 + .../com.example-lab3_2.12-provided.xml | 13 + .../reports/com.example-lab3_2.12-rpm.xml | 13 + ...com.example-lab3_2.12-runtime-internal.xml | 1298 + .../reports/com.example-lab3_2.12-runtime.xml | 1298 + .../com.example-lab3_2.12-scala-tool.xml | 76 + .../com.example-lab3_2.12-test-internal.xml | 1884 + .../reports/com.example-lab3_2.12-test.xml | 1898 + .../com.example-lab3_2.12-universal-docs.xml | 13 + .../com.example-lab3_2.12-universal-src.xml | 13 + .../com.example-lab3_2.12-universal.xml | 13 + .../reports/com.example-lab3_2.12-windows.xml | 13 + .../resolution-cache/reports/ivy-report.css | 279 + .../resolution-cache/reports/ivy-report.xsl | 514 + .../main/controllers/ReverseRoutes.scala | 117 + .../javascript/JavaScriptReverseRoutes.scala | 160 + .../routes/main/controllers/routes.java | 23 + .../controllers/security/ReverseRoutes.scala | 43 + .../javascript/JavaScriptReverseRoutes.scala | 56 + .../main/controllers/security/routes.java | 19 + .../routes/main/router/Routes.scala | 436 + .../routes/main/router/RoutesPrefix.scala | 16 + .../views/html/listProducts.template.scala | 127 + .../main/views/html/login.template.scala | 93 + .../twirl/main/views/html/main.template.scala | 127 + .../productAdmin/addProduct.template.scala | 94 + .../productAdmin/listProducts.template.scala | 134 + .../html/productAdmin/main.template.scala | 131 + .../productAdmin/updateProduct.template.scala | 98 + .../views/html/productDetails.template.scala | 97 + .../$global/$global/$global/streams/out | 0 .../streams/sync-exported-assets-web-assets | 1 + .../streams/$global/clean/$global/streams/out | 0 .../streams/update_cache_2.12/input_dsp | 1 + .../streams/update_cache_2.12/output_dsp | 1 + .../ivyConfiguration/$global/streams/out | 3 + .../$global/ivySbt/$global/streams/out | 0 .../playCommonClassloader/$global/streams/out | 1 + .../playCompileEverything/$global/streams/out | 0 .../projectDescriptors/$global/streams/out | 0 .../$global/update/$global/streams/out | 25983 +++++++++++ .../$global/streams/update_cache_2.12/inputs | 1 + .../$global/streams/update_cache_2.12/output | 1 + .../$global/discoveredMainClasses/data | 1 + .../compile/compile/$global/streams/out | 13 + .../$global/streams/inc_compile_2.12.zip | Bin 0 -> 15694 bytes .../compileIncremental/$global/streams/export | 1 + .../compileIncremental/$global/streams/out | 29 + .../$global/streams/copy-resources | 1 + .../compile/copyResources/$global/streams/out | 9 + .../$global/streams/export | 1 + .../exportedProducts/$global/streams/export | 1 + .../$global/streams/export | 1 + .../$global/streams/export | 1 + .../managedClasspath/$global/streams/export | 1 + .../manipulateBytecode/$global/streams/out | 0 .../$global/streams/play_instrumentation_2.12 | 1 + .../$global/streams/play_instrumentation_2.12 | 1 + .../playRoutes/$global/streams/op-cache | 1 + .../twirlCompileTemplates/$global/streams/out | 0 .../unmanagedClasspath/$global/streams/export | 1 + .../unmanagedJars/$global/streams/export | 1 + .../exportedProducts/$global/streams/export | 1 + .../$global/streams/export | 1 + .../$global/streams/export | 1 + .../managedClasspath/$global/streams/export | 1 + .../unmanagedClasspath/$global/streams/export | 1 + .../unmanagedJars/$global/streams/export | 1 + .../$global/streams/sync-assets-web-assets | 1 + .../lab3/1.0-SNAPSHOT/images/favicon.png | Bin 0 -> 687 bytes .../1.0-SNAPSHOT/images/productImages/1.jpg | Bin 0 -> 6149 bytes .../1.0-SNAPSHOT/images/productImages/10.jpg | Bin 0 -> 22509 bytes .../1.0-SNAPSHOT/images/productImages/11.jpg | Bin 0 -> 7106 bytes .../1.0-SNAPSHOT/images/productImages/12.jpg | Bin 0 -> 4241 bytes .../1.0-SNAPSHOT/images/productImages/13.jpg | Bin 0 -> 11680 bytes .../1.0-SNAPSHOT/images/productImages/14.jpg | Bin 0 -> 11680 bytes .../1.0-SNAPSHOT/images/productImages/14.png | Bin 0 -> 4332 bytes .../1.0-SNAPSHOT/images/productImages/15.jpg | Bin 0 -> 11680 bytes .../1.0-SNAPSHOT/images/productImages/2.jpg | Bin 0 -> 24319 bytes .../1.0-SNAPSHOT/images/productImages/3.jpg | Bin 0 -> 8693 bytes .../1.0-SNAPSHOT/images/productImages/4.jpg | Bin 0 -> 7415 bytes .../1.0-SNAPSHOT/images/productImages/45.jpg | Bin 0 -> 10903 bytes .../1.0-SNAPSHOT/images/productImages/46.jpg | Bin 0 -> 10903 bytes .../1.0-SNAPSHOT/images/productImages/6.jpg | Bin 0 -> 22264 bytes .../1.0-SNAPSHOT/images/productImages/7.jpg | Bin 0 -> 22009 bytes .../1.0-SNAPSHOT/images/productImages/8.jpg | Bin 0 -> 10567 bytes .../1.0-SNAPSHOT/images/productImages/9.jpg | Bin 0 -> 4261 bytes .../images/productImages/thumbnails/1.jpg | Bin 0 -> 1810 bytes .../images/productImages/thumbnails/10.jpg | Bin 0 -> 6275 bytes .../images/productImages/thumbnails/11.jpg | Bin 0 -> 953 bytes .../images/productImages/thumbnails/12.jpg | Bin 0 -> 1746 bytes .../images/productImages/thumbnails/13.jpg | Bin 0 -> 3121 bytes .../images/productImages/thumbnails/14.jpg | Bin 0 -> 3121 bytes .../images/productImages/thumbnails/15.jpg | Bin 0 -> 3121 bytes .../images/productImages/thumbnails/2.jpg | Bin 0 -> 4968 bytes .../images/productImages/thumbnails/3.jpg | Bin 0 -> 1664 bytes .../images/productImages/thumbnails/4.jpg | Bin 0 -> 952 bytes .../images/productImages/thumbnails/45.jpg | Bin 0 -> 1160 bytes .../images/productImages/thumbnails/46.jpg | Bin 0 -> 1160 bytes .../images/productImages/thumbnails/6.jpg | Bin 0 -> 1964 bytes .../images/productImages/thumbnails/7.jpg | Bin 0 -> 2940 bytes .../images/productImages/thumbnails/8.jpg | Bin 0 -> 2050 bytes .../images/productImages/thumbnails/9.jpg | Bin 0 -> 824 bytes .../productImages/thumbnails/noImage.jpg | Bin 0 -> 1647 bytes .../lab3/1.0-SNAPSHOT/javascripts/main.js | 3 + .../lab3/1.0-SNAPSHOT/stylesheets/main.css | 3 + target/web/public/main/images/favicon.png | Bin 0 -> 687 bytes .../public/main/images/productImages/1.jpg | Bin 0 -> 6149 bytes .../public/main/images/productImages/10.jpg | Bin 0 -> 22509 bytes .../public/main/images/productImages/11.jpg | Bin 0 -> 7106 bytes .../public/main/images/productImages/12.jpg | Bin 0 -> 4241 bytes .../public/main/images/productImages/13.jpg | Bin 0 -> 11680 bytes .../public/main/images/productImages/14.jpg | Bin 0 -> 11680 bytes .../public/main/images/productImages/14.png | Bin 0 -> 4332 bytes .../public/main/images/productImages/15.jpg | Bin 0 -> 11680 bytes .../public/main/images/productImages/2.jpg | Bin 0 -> 24319 bytes .../public/main/images/productImages/3.jpg | Bin 0 -> 8693 bytes .../public/main/images/productImages/4.jpg | Bin 0 -> 7415 bytes .../public/main/images/productImages/45.jpg | Bin 0 -> 10903 bytes .../public/main/images/productImages/46.jpg | Bin 0 -> 10903 bytes .../public/main/images/productImages/6.jpg | Bin 0 -> 22264 bytes .../public/main/images/productImages/7.jpg | Bin 0 -> 22009 bytes .../public/main/images/productImages/8.jpg | Bin 0 -> 10567 bytes .../public/main/images/productImages/9.jpg | Bin 0 -> 4261 bytes .../images/productImages/thumbnails/1.jpg | Bin 0 -> 1810 bytes .../images/productImages/thumbnails/10.jpg | Bin 0 -> 6275 bytes .../images/productImages/thumbnails/11.jpg | Bin 0 -> 953 bytes .../images/productImages/thumbnails/12.jpg | Bin 0 -> 1746 bytes .../images/productImages/thumbnails/13.jpg | Bin 0 -> 3121 bytes .../images/productImages/thumbnails/14.jpg | Bin 0 -> 3121 bytes .../images/productImages/thumbnails/15.jpg | Bin 0 -> 3121 bytes .../images/productImages/thumbnails/2.jpg | Bin 0 -> 4968 bytes .../images/productImages/thumbnails/3.jpg | Bin 0 -> 1664 bytes .../images/productImages/thumbnails/4.jpg | Bin 0 -> 952 bytes .../images/productImages/thumbnails/45.jpg | Bin 0 -> 1160 bytes .../images/productImages/thumbnails/46.jpg | Bin 0 -> 1160 bytes .../images/productImages/thumbnails/6.jpg | Bin 0 -> 1964 bytes .../images/productImages/thumbnails/7.jpg | Bin 0 -> 2940 bytes .../images/productImages/thumbnails/8.jpg | Bin 0 -> 2050 bytes .../images/productImages/thumbnails/9.jpg | Bin 0 -> 824 bytes .../productImages/thumbnails/noImage.jpg | Bin 0 -> 1647 bytes target/web/public/main/javascripts/main.js | 3 + target/web/public/main/stylesheets/main.css | 3 + test/controllers/HomeControllerTest.java | 32 + 435 files changed, 176286 insertions(+) create mode 100644 .g8/form/app/controllers/$model__Camel$Controller.java create mode 100644 .g8/form/app/controllers/$model__Camel$Data.java create mode 100644 .g8/form/app/views/$model__camel$/form.scala.html create mode 100644 .g8/form/default.properties create mode 100644 .g8/form/generated-test/README.md create mode 100644 .g8/form/generated-test/controllers/$model__Camel$ControllerTest.java create mode 100644 .gradle/4.4/fileChanges/last-build.bin create mode 100644 .gradle/4.4/fileHashes/fileHashes.bin create mode 100644 .gradle/4.4/fileHashes/fileHashes.lock create mode 100644 .project create mode 100644 .settings/org.eclipse.buildship.core.prefs create mode 100644 .vscode/settings.json create mode 100644 app/controllers/AdminProductCtrl.java create mode 100644 app/controllers/ProductCtrl.java create mode 100644 app/controllers/security/CheckIfAdmin.java create mode 100644 app/controllers/security/CheckIfCustomer.java create mode 100644 app/controllers/security/LoginCtrl.java create mode 100644 app/controllers/security/Secured.java create mode 100644 app/models/products/Category.java create mode 100644 app/models/products/Product.java create mode 100644 app/models/users/Administrator.java create mode 100644 app/models/users/Customer.java create mode 100644 app/models/users/Login.java create mode 100644 app/models/users/Manager.java create mode 100644 app/models/users/User.java create mode 100644 app/views/listProducts.scala.html create mode 100644 app/views/login.scala.html create mode 100644 app/views/main.scala.html create mode 100644 app/views/productAdmin/addProduct.scala.html create mode 100644 app/views/productAdmin/listProducts.scala.html create mode 100644 app/views/productAdmin/main.scala.html create mode 100644 app/views/productAdmin/updateProduct.scala.html create mode 100644 app/views/productDetails.scala.html create mode 100644 build.gradle create mode 100644 build.sbt create mode 100644 conf/application.conf create mode 100644 conf/evolutions/default/1.sql create mode 100644 conf/evolutions/default/2.sql create mode 100644 conf/evolutions/default/3.sql create mode 100644 conf/logback.xml create mode 100644 conf/routes create mode 100644 data/productsDB.mv.db create mode 100644 data/productsDB.trace.db create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 lib/im4java-1.4.0-1.5.jar create mode 100644 logs/application.log create mode 100644 project/build.properties create mode 100644 project/plugins.sbt create mode 100644 project/project/target/config-classes/$3f5b9005ed72c01f76f6$.class create mode 100644 project/project/target/config-classes/$3f5b9005ed72c01f76f6.cache create mode 100644 project/project/target/config-classes/$3f5b9005ed72c01f76f6.class create mode 100644 project/project/target/config-classes/$5d5834882062acfd1e5b$.class create mode 100644 project/project/target/config-classes/$5d5834882062acfd1e5b.cache create mode 100644 project/project/target/config-classes/$5d5834882062acfd1e5b.class create mode 100644 project/scaffold.sbt create mode 100644 project/target/config-classes/$15edceac93bbbc2d0ec9$.class create mode 100644 project/target/config-classes/$15edceac93bbbc2d0ec9.cache create mode 100644 project/target/config-classes/$15edceac93bbbc2d0ec9.class create mode 100644 project/target/config-classes/$367aab8432d8362236c3$.class create mode 100644 project/target/config-classes/$367aab8432d8362236c3.cache create mode 100644 project/target/config-classes/$367aab8432d8362236c3.class create mode 100644 project/target/config-classes/$379f864cd7690c0ed3b6$.class create mode 100644 project/target/config-classes/$379f864cd7690c0ed3b6.cache create mode 100644 project/target/config-classes/$379f864cd7690c0ed3b6.class create mode 100644 project/target/config-classes/$4cfd96b442a0e386d0aa$.class create mode 100644 project/target/config-classes/$4cfd96b442a0e386d0aa.cache create mode 100644 project/target/config-classes/$4cfd96b442a0e386d0aa.class create mode 100644 project/target/config-classes/$64c185fa21f6207ce868$.class create mode 100644 project/target/config-classes/$64c185fa21f6207ce868.cache create mode 100644 project/target/config-classes/$64c185fa21f6207ce868.class create mode 100644 project/target/config-classes/$66b18781b0dc04725c19$.class create mode 100644 project/target/config-classes/$66b18781b0dc04725c19.cache create mode 100644 project/target/config-classes/$66b18781b0dc04725c19.class create mode 100644 project/target/config-classes/$83d00abc169193955584$.class create mode 100644 project/target/config-classes/$83d00abc169193955584.cache create mode 100644 project/target/config-classes/$83d00abc169193955584.class create mode 100644 project/target/config-classes/$baf5680579e409f4dde1$.class create mode 100644 project/target/config-classes/$baf5680579e409f4dde1.cache create mode 100644 project/target/config-classes/$baf5680579e409f4dde1.class create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/default/crudauthentication-build/scala_2.12/sbt_1.0/0.1-SNAPSHOT/resolved.xml.properties create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/default/crudauthentication-build/scala_2.12/sbt_1.0/0.1-SNAPSHOT/resolved.xml.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/default/lab1imageupload-build/scala_2.12/sbt_1.0/0.1-SNAPSHOT/resolved.xml.properties create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/default/lab1imageupload-build/scala_2.12/sbt_1.0/0.1-SNAPSHOT/resolved.xml.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/default/lab2skeleton-build/scala_2.12/sbt_1.0/0.1-SNAPSHOT/resolved.xml.properties create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/default/lab2skeleton-build/scala_2.12/sbt_1.0/0.1-SNAPSHOT/resolved.xml.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/default/lab3-build/scala_2.12/sbt_1.0/0.1-SNAPSHOT/resolved.xml.properties create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/default/lab3-build/scala_2.12/sbt_1.0/0.1-SNAPSHOT/resolved.xml.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/default/lab3solution-build/scala_2.12/sbt_1.0/0.1-SNAPSHOT/resolved.xml.properties create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/default/lab3solution-build/scala_2.12/sbt_1.0/0.1-SNAPSHOT/resolved.xml.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/default/lab4skeleton-build/scala_2.12/sbt_1.0/0.1-SNAPSHOT/resolved.xml.properties create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/default/lab4skeleton-build/scala_2.12/sbt_1.0/0.1-SNAPSHOT/resolved.xml.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-crudauthentication-build-compile-internal.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-crudauthentication-build-compile.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-crudauthentication-build-optional.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-crudauthentication-build-plugin.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-crudauthentication-build-pom.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-crudauthentication-build-provided.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-crudauthentication-build-runtime-internal.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-crudauthentication-build-runtime.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-crudauthentication-build-scala-tool.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-crudauthentication-build-test-internal.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-crudauthentication-build-test.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab1imageupload-build-compile-internal.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab1imageupload-build-compile.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab1imageupload-build-optional.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab1imageupload-build-plugin.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab1imageupload-build-pom.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab1imageupload-build-provided.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab1imageupload-build-runtime-internal.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab1imageupload-build-runtime.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab1imageupload-build-scala-tool.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab1imageupload-build-test-internal.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab1imageupload-build-test.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab2skeleton-build-compile-internal.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab2skeleton-build-compile.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab2skeleton-build-optional.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab2skeleton-build-plugin.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab2skeleton-build-pom.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab2skeleton-build-provided.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab2skeleton-build-runtime-internal.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab2skeleton-build-runtime.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab2skeleton-build-scala-tool.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab2skeleton-build-test-internal.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab2skeleton-build-test.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab3-build-compile-internal.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab3-build-compile.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab3-build-optional.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab3-build-plugin.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab3-build-pom.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab3-build-provided.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab3-build-runtime-internal.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab3-build-runtime.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab3-build-scala-tool.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab3-build-test-internal.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab3-build-test.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab3solution-build-compile-internal.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab3solution-build-compile.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab3solution-build-optional.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab3solution-build-plugin.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab3solution-build-pom.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab3solution-build-provided.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab3solution-build-runtime-internal.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab3solution-build-runtime.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab3solution-build-scala-tool.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab3solution-build-test-internal.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab3solution-build-test.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab4skeleton-build-compile-internal.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab4skeleton-build-compile.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab4skeleton-build-optional.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab4skeleton-build-plugin.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab4skeleton-build-pom.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab4skeleton-build-provided.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab4skeleton-build-runtime-internal.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab4skeleton-build-runtime.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab4skeleton-build-scala-tool.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab4skeleton-build-test-internal.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/default-lab4skeleton-build-test.xml create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/ivy-report.css create mode 100644 project/target/scala-2.12/sbt-1.0/resolution-cache/reports/ivy-report.xsl create mode 100644 project/target/streams/$global/$global/$global/streams/out create mode 100644 project/target/streams/$global/dependencyPositions/$global/streams/update_cache_2.12/input_dsp create mode 100644 project/target/streams/$global/dependencyPositions/$global/streams/update_cache_2.12/output_dsp create mode 100644 project/target/streams/$global/ivyConfiguration/$global/streams/out create mode 100644 project/target/streams/$global/ivySbt/$global/streams/out create mode 100644 project/target/streams/$global/projectDescriptors/$global/streams/out create mode 100644 project/target/streams/$global/update/$global/streams/out create mode 100644 project/target/streams/$global/update/$global/streams/update_cache_2.12/inputs create mode 100644 project/target/streams/$global/update/$global/streams/update_cache_2.12/output create mode 100644 project/target/streams/compile/$global/$global/discoveredMainClasses/data create mode 100644 project/target/streams/compile/compile/$global/streams/out create mode 100644 project/target/streams/compile/compileIncremental/$global/streams/export create mode 100644 project/target/streams/compile/compileIncremental/$global/streams/out create mode 100644 project/target/streams/compile/copyResources/$global/streams/copy-resources create mode 100644 project/target/streams/compile/copyResources/$global/streams/out create mode 100644 project/target/streams/compile/dependencyClasspath/$global/streams/export create mode 100644 project/target/streams/compile/exportedProducts/$global/streams/export create mode 100644 project/target/streams/compile/externalDependencyClasspath/$global/streams/export create mode 100644 project/target/streams/compile/internalDependencyClasspath/$global/streams/export create mode 100644 project/target/streams/compile/managedClasspath/$global/streams/export create mode 100644 project/target/streams/compile/unmanagedClasspath/$global/streams/export create mode 100644 project/target/streams/compile/unmanagedJars/$global/streams/export create mode 100644 project/target/streams/runtime/dependencyClasspath/$global/streams/export create mode 100644 project/target/streams/runtime/exportedProducts/$global/streams/export create mode 100644 project/target/streams/runtime/externalDependencyClasspath/$global/streams/export create mode 100644 project/target/streams/runtime/fullClasspath/$global/streams/export create mode 100644 project/target/streams/runtime/internalDependencyClasspath/$global/streams/export create mode 100644 project/target/streams/runtime/managedClasspath/$global/streams/export create mode 100644 project/target/streams/runtime/unmanagedClasspath/$global/streams/export create mode 100644 project/target/streams/runtime/unmanagedJars/$global/streams/export create mode 100644 public/images/favicon.png create mode 100644 public/images/productImages/1.jpg create mode 100644 public/images/productImages/10.jpg create mode 100644 public/images/productImages/11.jpg create mode 100644 public/images/productImages/12.jpg create mode 100644 public/images/productImages/13.jpg create mode 100644 public/images/productImages/14.jpg create mode 100644 public/images/productImages/14.png create mode 100644 public/images/productImages/15.jpg create mode 100644 public/images/productImages/2.jpg create mode 100644 public/images/productImages/3.jpg create mode 100644 public/images/productImages/4.jpg create mode 100644 public/images/productImages/45.jpg create mode 100644 public/images/productImages/46.jpg create mode 100644 public/images/productImages/6.jpg create mode 100644 public/images/productImages/7.jpg create mode 100644 public/images/productImages/8.jpg create mode 100644 public/images/productImages/9.jpg create mode 100644 public/images/productImages/thumbnails/1.jpg create mode 100644 public/images/productImages/thumbnails/10.jpg create mode 100644 public/images/productImages/thumbnails/11.jpg create mode 100644 public/images/productImages/thumbnails/12.jpg create mode 100644 public/images/productImages/thumbnails/13.jpg create mode 100644 public/images/productImages/thumbnails/14.jpg create mode 100644 public/images/productImages/thumbnails/15.jpg create mode 100644 public/images/productImages/thumbnails/2.jpg create mode 100644 public/images/productImages/thumbnails/3.jpg create mode 100644 public/images/productImages/thumbnails/4.jpg create mode 100644 public/images/productImages/thumbnails/45.jpg create mode 100644 public/images/productImages/thumbnails/46.jpg create mode 100644 public/images/productImages/thumbnails/6.jpg create mode 100644 public/images/productImages/thumbnails/7.jpg create mode 100644 public/images/productImages/thumbnails/8.jpg create mode 100644 public/images/productImages/thumbnails/9.jpg create mode 100644 public/images/productImages/thumbnails/noImage.jpg create mode 100644 public/javascripts/main.js create mode 100644 public/stylesheets/main.css create mode 100644 target/.history create mode 100644 target/scala-2.12/classes/application.conf create mode 100644 target/scala-2.12/classes/controllers/AdminProductCtrl.class create mode 100644 target/scala-2.12/classes/controllers/ProductCtrl.class create mode 100644 target/scala-2.12/classes/controllers/ReverseAdminProductCtrl.class create mode 100644 target/scala-2.12/classes/controllers/ReverseAssets.class create mode 100644 target/scala-2.12/classes/controllers/ReverseProductCtrl.class create mode 100644 target/scala-2.12/classes/controllers/Secured.class create mode 100644 target/scala-2.12/classes/controllers/javascript/ReverseAdminProductCtrl.class create mode 100644 target/scala-2.12/classes/controllers/javascript/ReverseAssets.class create mode 100644 target/scala-2.12/classes/controllers/javascript/ReverseProductCtrl.class create mode 100644 target/scala-2.12/classes/controllers/routes$javascript.class create mode 100644 target/scala-2.12/classes/controllers/routes.class create mode 100644 target/scala-2.12/classes/controllers/security/CheckIfAdmin.class create mode 100644 target/scala-2.12/classes/controllers/security/CheckIfCustomer.class create mode 100644 target/scala-2.12/classes/controllers/security/LoginCtrl.class create mode 100644 target/scala-2.12/classes/controllers/security/ReverseLoginCtrl.class create mode 100644 target/scala-2.12/classes/controllers/security/javascript/ReverseLoginCtrl.class create mode 100644 target/scala-2.12/classes/controllers/security/routes$javascript.class create mode 100644 target/scala-2.12/classes/controllers/security/routes.class create mode 100644 target/scala-2.12/classes/evolutions/default/1.sql create mode 100644 target/scala-2.12/classes/evolutions/default/2.sql create mode 100644 target/scala-2.12/classes/evolutions/default/3.sql create mode 100644 target/scala-2.12/classes/logback.xml create mode 100644 target/scala-2.12/classes/models/products/Category.class create mode 100644 target/scala-2.12/classes/models/products/Product.class create mode 100644 target/scala-2.12/classes/models/users/Administrator.class create mode 100644 target/scala-2.12/classes/models/users/Customer.class create mode 100644 target/scala-2.12/classes/models/users/Login.class create mode 100644 target/scala-2.12/classes/models/users/Manager.class create mode 100644 target/scala-2.12/classes/models/users/User.class create mode 100644 target/scala-2.12/classes/router/Routes$$anonfun$routes$1.class create mode 100644 target/scala-2.12/classes/router/Routes.class create mode 100644 target/scala-2.12/classes/router/RoutesPrefix$.class create mode 100644 target/scala-2.12/classes/router/RoutesPrefix.class create mode 100644 target/scala-2.12/classes/routes create mode 100644 target/scala-2.12/classes/views/html/listProducts$.class create mode 100644 target/scala-2.12/classes/views/html/listProducts.class create mode 100644 target/scala-2.12/classes/views/html/login$.class create mode 100644 target/scala-2.12/classes/views/html/login.class create mode 100644 target/scala-2.12/classes/views/html/main$.class create mode 100644 target/scala-2.12/classes/views/html/main.class create mode 100644 target/scala-2.12/classes/views/html/productAdmin/addProduct$.class create mode 100644 target/scala-2.12/classes/views/html/productAdmin/addProduct.class create mode 100644 target/scala-2.12/classes/views/html/productAdmin/listProducts$.class create mode 100644 target/scala-2.12/classes/views/html/productAdmin/listProducts.class create mode 100644 target/scala-2.12/classes/views/html/productAdmin/main$.class create mode 100644 target/scala-2.12/classes/views/html/productAdmin/main.class create mode 100644 target/scala-2.12/classes/views/html/productAdmin/updateProduct$.class create mode 100644 target/scala-2.12/classes/views/html/productAdmin/updateProduct.class create mode 100644 target/scala-2.12/classes/views/html/productDetails$.class create mode 100644 target/scala-2.12/classes/views/html/productDetails.class create mode 100644 target/scala-2.12/resolution-cache/com.example/lab3_2.12/1.0-SNAPSHOT/resolved.xml.properties create mode 100644 target/scala-2.12/resolution-cache/com.example/lab3_2.12/1.0-SNAPSHOT/resolved.xml.xml create mode 100644 target/scala-2.12/resolution-cache/reports/com.example-lab3_2.12-compile-internal.xml create mode 100644 target/scala-2.12/resolution-cache/reports/com.example-lab3_2.12-compile.xml create mode 100644 target/scala-2.12/resolution-cache/reports/com.example-lab3_2.12-debian.xml create mode 100644 target/scala-2.12/resolution-cache/reports/com.example-lab3_2.12-docker.xml create mode 100644 target/scala-2.12/resolution-cache/reports/com.example-lab3_2.12-docs.xml create mode 100644 target/scala-2.12/resolution-cache/reports/com.example-lab3_2.12-linux.xml create mode 100644 target/scala-2.12/resolution-cache/reports/com.example-lab3_2.12-optional.xml create mode 100644 target/scala-2.12/resolution-cache/reports/com.example-lab3_2.12-plugin.xml create mode 100644 target/scala-2.12/resolution-cache/reports/com.example-lab3_2.12-pom.xml create mode 100644 target/scala-2.12/resolution-cache/reports/com.example-lab3_2.12-provided.xml create mode 100644 target/scala-2.12/resolution-cache/reports/com.example-lab3_2.12-rpm.xml create mode 100644 target/scala-2.12/resolution-cache/reports/com.example-lab3_2.12-runtime-internal.xml create mode 100644 target/scala-2.12/resolution-cache/reports/com.example-lab3_2.12-runtime.xml create mode 100644 target/scala-2.12/resolution-cache/reports/com.example-lab3_2.12-scala-tool.xml create mode 100644 target/scala-2.12/resolution-cache/reports/com.example-lab3_2.12-test-internal.xml create mode 100644 target/scala-2.12/resolution-cache/reports/com.example-lab3_2.12-test.xml create mode 100644 target/scala-2.12/resolution-cache/reports/com.example-lab3_2.12-universal-docs.xml create mode 100644 target/scala-2.12/resolution-cache/reports/com.example-lab3_2.12-universal-src.xml create mode 100644 target/scala-2.12/resolution-cache/reports/com.example-lab3_2.12-universal.xml create mode 100644 target/scala-2.12/resolution-cache/reports/com.example-lab3_2.12-windows.xml create mode 100644 target/scala-2.12/resolution-cache/reports/ivy-report.css create mode 100644 target/scala-2.12/resolution-cache/reports/ivy-report.xsl create mode 100644 target/scala-2.12/routes/main/controllers/ReverseRoutes.scala create mode 100644 target/scala-2.12/routes/main/controllers/javascript/JavaScriptReverseRoutes.scala create mode 100644 target/scala-2.12/routes/main/controllers/routes.java create mode 100644 target/scala-2.12/routes/main/controllers/security/ReverseRoutes.scala create mode 100644 target/scala-2.12/routes/main/controllers/security/javascript/JavaScriptReverseRoutes.scala create mode 100644 target/scala-2.12/routes/main/controllers/security/routes.java create mode 100644 target/scala-2.12/routes/main/router/Routes.scala create mode 100644 target/scala-2.12/routes/main/router/RoutesPrefix.scala create mode 100644 target/scala-2.12/twirl/main/views/html/listProducts.template.scala create mode 100644 target/scala-2.12/twirl/main/views/html/login.template.scala create mode 100644 target/scala-2.12/twirl/main/views/html/main.template.scala create mode 100644 target/scala-2.12/twirl/main/views/html/productAdmin/addProduct.template.scala create mode 100644 target/scala-2.12/twirl/main/views/html/productAdmin/listProducts.template.scala create mode 100644 target/scala-2.12/twirl/main/views/html/productAdmin/main.template.scala create mode 100644 target/scala-2.12/twirl/main/views/html/productAdmin/updateProduct.template.scala create mode 100644 target/scala-2.12/twirl/main/views/html/productDetails.template.scala create mode 100644 target/streams/$global/$global/$global/streams/out create mode 100644 target/streams/$global/$global/$global/streams/sync-exported-assets-web-assets create mode 100644 target/streams/$global/clean/$global/streams/out create mode 100644 target/streams/$global/dependencyPositions/$global/streams/update_cache_2.12/input_dsp create mode 100644 target/streams/$global/dependencyPositions/$global/streams/update_cache_2.12/output_dsp create mode 100644 target/streams/$global/ivyConfiguration/$global/streams/out create mode 100644 target/streams/$global/ivySbt/$global/streams/out create mode 100644 target/streams/$global/playCommonClassloader/$global/streams/out create mode 100644 target/streams/$global/playCompileEverything/$global/streams/out create mode 100644 target/streams/$global/projectDescriptors/$global/streams/out create mode 100644 target/streams/$global/update/$global/streams/out create mode 100644 target/streams/$global/update/$global/streams/update_cache_2.12/inputs create mode 100644 target/streams/$global/update/$global/streams/update_cache_2.12/output create mode 100644 target/streams/compile/$global/$global/discoveredMainClasses/data create mode 100644 target/streams/compile/compile/$global/streams/out create mode 100644 target/streams/compile/compileIncSetup/$global/streams/inc_compile_2.12.zip create mode 100644 target/streams/compile/compileIncremental/$global/streams/export create mode 100644 target/streams/compile/compileIncremental/$global/streams/out create mode 100644 target/streams/compile/copyResources/$global/streams/copy-resources create mode 100644 target/streams/compile/copyResources/$global/streams/out create mode 100644 target/streams/compile/dependencyClasspath/$global/streams/export create mode 100644 target/streams/compile/exportedProducts/$global/streams/export create mode 100644 target/streams/compile/externalDependencyClasspath/$global/streams/export create mode 100644 target/streams/compile/internalDependencyClasspath/$global/streams/export create mode 100644 target/streams/compile/managedClasspath/$global/streams/export create mode 100644 target/streams/compile/manipulateBytecode/$global/streams/out create mode 100644 target/streams/compile/playEnhancerGenerateAccessors/$global/streams/play_instrumentation_2.12 create mode 100644 target/streams/compile/playEnhancerRewriteAccessors/$global/streams/play_instrumentation_2.12 create mode 100644 target/streams/compile/playRoutes/$global/streams/op-cache create mode 100644 target/streams/compile/twirlCompileTemplates/$global/streams/out create mode 100644 target/streams/compile/unmanagedClasspath/$global/streams/export create mode 100644 target/streams/compile/unmanagedJars/$global/streams/export create mode 100644 target/streams/runtime/exportedProducts/$global/streams/export create mode 100644 target/streams/runtime/externalDependencyClasspath/$global/streams/export create mode 100644 target/streams/runtime/internalDependencyClasspath/$global/streams/export create mode 100644 target/streams/runtime/managedClasspath/$global/streams/export create mode 100644 target/streams/runtime/unmanagedClasspath/$global/streams/export create mode 100644 target/streams/runtime/unmanagedJars/$global/streams/export create mode 100644 target/streams/web-assets/assets/$global/streams/sync-assets-web-assets create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/favicon.png create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/1.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/10.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/11.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/12.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/13.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/14.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/14.png create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/15.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/2.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/3.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/4.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/45.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/46.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/6.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/7.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/8.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/9.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/thumbnails/1.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/thumbnails/10.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/thumbnails/11.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/thumbnails/12.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/thumbnails/13.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/thumbnails/14.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/thumbnails/15.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/thumbnails/2.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/thumbnails/3.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/thumbnails/4.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/thumbnails/45.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/thumbnails/46.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/thumbnails/6.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/thumbnails/7.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/thumbnails/8.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/thumbnails/9.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/images/productImages/thumbnails/noImage.jpg create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/javascripts/main.js create mode 100644 target/web/classes/main/META-INF/resources/webjars/lab3/1.0-SNAPSHOT/stylesheets/main.css create mode 100644 target/web/public/main/images/favicon.png create mode 100644 target/web/public/main/images/productImages/1.jpg create mode 100644 target/web/public/main/images/productImages/10.jpg create mode 100644 target/web/public/main/images/productImages/11.jpg create mode 100644 target/web/public/main/images/productImages/12.jpg create mode 100644 target/web/public/main/images/productImages/13.jpg create mode 100644 target/web/public/main/images/productImages/14.jpg create mode 100644 target/web/public/main/images/productImages/14.png create mode 100644 target/web/public/main/images/productImages/15.jpg create mode 100644 target/web/public/main/images/productImages/2.jpg create mode 100644 target/web/public/main/images/productImages/3.jpg create mode 100644 target/web/public/main/images/productImages/4.jpg create mode 100644 target/web/public/main/images/productImages/45.jpg create mode 100644 target/web/public/main/images/productImages/46.jpg create mode 100644 target/web/public/main/images/productImages/6.jpg create mode 100644 target/web/public/main/images/productImages/7.jpg create mode 100644 target/web/public/main/images/productImages/8.jpg create mode 100644 target/web/public/main/images/productImages/9.jpg create mode 100644 target/web/public/main/images/productImages/thumbnails/1.jpg create mode 100644 target/web/public/main/images/productImages/thumbnails/10.jpg create mode 100644 target/web/public/main/images/productImages/thumbnails/11.jpg create mode 100644 target/web/public/main/images/productImages/thumbnails/12.jpg create mode 100644 target/web/public/main/images/productImages/thumbnails/13.jpg create mode 100644 target/web/public/main/images/productImages/thumbnails/14.jpg create mode 100644 target/web/public/main/images/productImages/thumbnails/15.jpg create mode 100644 target/web/public/main/images/productImages/thumbnails/2.jpg create mode 100644 target/web/public/main/images/productImages/thumbnails/3.jpg create mode 100644 target/web/public/main/images/productImages/thumbnails/4.jpg create mode 100644 target/web/public/main/images/productImages/thumbnails/45.jpg create mode 100644 target/web/public/main/images/productImages/thumbnails/46.jpg create mode 100644 target/web/public/main/images/productImages/thumbnails/6.jpg create mode 100644 target/web/public/main/images/productImages/thumbnails/7.jpg create mode 100644 target/web/public/main/images/productImages/thumbnails/8.jpg create mode 100644 target/web/public/main/images/productImages/thumbnails/9.jpg create mode 100644 target/web/public/main/images/productImages/thumbnails/noImage.jpg create mode 100644 target/web/public/main/javascripts/main.js create mode 100644 target/web/public/main/stylesheets/main.css create mode 100644 test/controllers/HomeControllerTest.java diff --git a/.g8/form/app/controllers/$model__Camel$Controller.java b/.g8/form/app/controllers/$model__Camel$Controller.java new file mode 100644 index 0000000..1ac4fe5 --- /dev/null +++ b/.g8/form/app/controllers/$model__Camel$Controller.java @@ -0,0 +1,43 @@ +package controllers; + +import play.data.Form; +import play.data.FormFactory; +import play.mvc.Controller; +import play.mvc.Result; + +import javax.inject.Inject; + +// Add the following to conf/routes +/* +GET /$model;format="camel"$ controllers.$model;format="Camel"$Controller.$model;format="camel"$Get +POST /$model;format="camel"$ controllers.$model;format="Camel"$Controller.$model;format="camel"$Post +*/ + +/** + * $model;format="Camel"$ form controller for Play Java + */ +public class $model;format="Camel"$Controller extends Controller { + + private final Form<$model;format="Camel"$Data> $model;format="camel"$Form; + + @Inject + public $model;format="Camel"$Controller(FormFactory formFactory) { + this.$model;format="camel"$Form = formFactory.form($model;format="Camel"$Data.class); + } + + public Result $model;format="camel"$Get() { + return ok(views.html.$model;format="camel"$.form.render($model;format="camel"$Form)); + } + + public Result $model;format="camel"$Post() { + Form<$model;format="Camel"$Data> boundForm = $model;format="camel"$Form.bindFromRequest(); + if (boundForm.hasErrors()) { + return badRequest(views.html.$model;format="camel"$.form.render(boundForm)); + } else { + $model;format="Camel"$Data $model;format="camel"$ = boundForm.get(); + flash("success", "$model;format="Camel"$ " + $model;format="camel"$); + return redirect(routes.$model;format="Camel"$Controller.$model;format="camel"$Get()); + } + } + +} diff --git a/.g8/form/app/controllers/$model__Camel$Data.java b/.g8/form/app/controllers/$model__Camel$Data.java new file mode 100644 index 0000000..50dc06f --- /dev/null +++ b/.g8/form/app/controllers/$model__Camel$Data.java @@ -0,0 +1,37 @@ +package controllers; + +import play.data.validation.Constraints; + +public class $model;format="Camel"$Data { + + @Constraints.Required + private String name; + + @Constraints.Required + private Integer age; + + public $model;format="Camel"$Data() { + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } + + @Override + public String toString() { + return String.format("$model;format="Camel"$Data(%s, %s)", name, age); + } + +} diff --git a/.g8/form/app/views/$model__camel$/form.scala.html b/.g8/form/app/views/$model__camel$/form.scala.html new file mode 100644 index 0000000..7bf9fd5 --- /dev/null +++ b/.g8/form/app/views/$model__camel$/form.scala.html @@ -0,0 +1,12 @@ +@($model;format="camel"$Form: Form[$model;format="Camel"$Data]) + +

$model;format="camel"$ form

+ +@flash.getOrDefault("success", "") + +@helper.form(action = routes.$model;format="Camel"$Controller.$model;format="camel"$Post()) { + @helper.CSRF.formField + @helper.inputText($model;format="camel"$Form("name")) + @helper.inputText($model;format="camel"$Form("age")) + +} diff --git a/.g8/form/default.properties b/.g8/form/default.properties new file mode 100644 index 0000000..32090f3 --- /dev/null +++ b/.g8/form/default.properties @@ -0,0 +1,2 @@ +description = Generates a Controller with form handling +model = user diff --git a/.g8/form/generated-test/README.md b/.g8/form/generated-test/README.md new file mode 100644 index 0000000..db01c87 --- /dev/null +++ b/.g8/form/generated-test/README.md @@ -0,0 +1 @@ +Temporary file until g8-scaffold will generate "test" directory diff --git a/.g8/form/generated-test/controllers/$model__Camel$ControllerTest.java b/.g8/form/generated-test/controllers/$model__Camel$ControllerTest.java new file mode 100644 index 0000000..7cdb870 --- /dev/null +++ b/.g8/form/generated-test/controllers/$model__Camel$ControllerTest.java @@ -0,0 +1,50 @@ +package controllers; + +import org.junit.Test; +import play.Application; +import play.filters.csrf.*; +import play.inject.guice.GuiceApplicationBuilder; +import play.mvc.*; +import play.test.WithApplication; + +import java.util.HashMap; + +import static org.junit.Assert.assertEquals; +import static play.mvc.Http.RequestBuilder; +import static play.mvc.Http.Status.OK; +import static play.test.Helpers.*; +import static play.api.test.CSRFTokenHelper.*; + +public class $model;format="Camel"$ControllerTest extends WithApplication { + + @Override + protected Application provideApplication() { + return new GuiceApplicationBuilder().build(); + } + + @Test + public void test$model;format="Camel"$Get() { + RequestBuilder request = new RequestBuilder() + .method(GET) + .uri("/$model;format="camel"$"); + + Result result = route(app, request); + assertEquals(OK, result.status()); + } + + @Test + public void test$model;format="Camel"$Post() { + HashMap formData = new HashMap<>(); + formData.put("name", "play"); + formData.put("age", "4"); + RequestBuilder request = addCSRFToken(new RequestBuilder() + .header(Http.HeaderNames.HOST, "localhost") + .method(POST) + .bodyForm(formData) + .uri("/$model;format="camel"$")); + + Result result = route(app, request); + assertEquals(SEE_OTHER, result.status()); + } + +} diff --git a/.gradle/4.4/fileChanges/last-build.bin b/.gradle/4.4/fileChanges/last-build.bin new file mode 100644 index 0000000000000000000000000000000000000000..f76dd238ade08917e6712764a16a22005a50573d GIT binary patch literal 1 IcmZPo000310RR91 literal 0 HcmV?d00001 diff --git a/.gradle/4.4/fileHashes/fileHashes.bin b/.gradle/4.4/fileHashes/fileHashes.bin new file mode 100644 index 0000000000000000000000000000000000000000..3008c2ef463b14f07eb0a42778b579f86abf2cba GIT binary patch literal 18547 zcmeI(F^WPl5CG8Vb|Ppa{MJrUWWf_CTUaS57M6l|1F`TBw%b}*c#OS>9ze?#1PjgQ zD_%k51(F$(X6Cg?enLpfx5o&tQF)~@0t5&UAV7cs0RjXF5FkK+009C72oNAZ;8O&~ zv5`X7Ow!D!Nog6vcQGcpYqCBKyT@8~-0M8=51ujZ*RwM#0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNCf4g&31MEcmjn$GfWwAw8G b8?F9!avJ>3F7dO#^t_+{WtDy%Vr<<3G2<*K literal 0 HcmV?d00001 diff --git a/.gradle/4.4/fileHashes/fileHashes.lock b/.gradle/4.4/fileHashes/fileHashes.lock new file mode 100644 index 0000000000000000000000000000000000000000..bff41fc6b800f3e395a89f55e33502dd07534e67 GIT binary patch literal 17 UcmZSn`E+e+_r-^Y86bce080G@_W%F@ literal 0 HcmV?d00001 diff --git a/.project b/.project new file mode 100644 index 0000000..c3b86e5 --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + lab3 + Project lab3 created by Buildship. + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/.settings/org.eclipse.buildship.core.prefs b/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 0000000..db9ad8c --- /dev/null +++ b/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,2 @@ +#Mon Mar 05 11:40:24 GMT 2018 +connection.project.dir= diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..0e14d8e --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "java.configuration.updateBuildConfiguration": "disabled" +} \ No newline at end of file diff --git a/app/controllers/AdminProductCtrl.java b/app/controllers/AdminProductCtrl.java new file mode 100644 index 0000000..bff8caa --- /dev/null +++ b/app/controllers/AdminProductCtrl.java @@ -0,0 +1,270 @@ +package controllers; + +import controllers.security.*; + +import play.mvc.*; +import play.api.Environment; +import play.data.*; +import play.db.ebean.Transactional; + +import java.util.ArrayList; +import java.util.List; +import javax.inject.Inject; + + +import models.users.*; +import models.products.*; +import views.html.productAdmin.*; + +import play.mvc.Http.*; +import play.mvc.Http.MultipartFormData.FilePart; +import java.io.File; + +import org.im4java.core.ConvertCmd; +import org.im4java.core.IMOperation; + +// Authenticate user +@Security.Authenticated(Secured.class) +// Authorise user (check if admin) +@With(CheckIfAdmin.class) + +/** + * This controller contains an action to handle HTTP requests + * to the application's home page. + */ +public class AdminProductCtrl extends Controller { + + /** + * An action that renders an HTML page with a welcome message. + * The configuration in the routes file means that + * this method will be called when the application receives a + * GET request with a path of /. + */ + private FormFactory formFactory; + private Environment e; + + @Inject + public AdminProductCtrl(FormFactory f,Environment env) { + this.formFactory = f; + this.e = env; + } + // Get a user - if logged in email will be set in the session + private User getCurrentUser() { + User u = User.getLoggedIn(session().get("email")); + return u; + } + public Result index() { + return redirect(controllers.routes.AdminProductCtrl.listProducts(0)); + } + // Get a list of products + // If cat parameter is 0 then return all products + // Otherwise return products for a category (by id) + // In both cases products will be searched using the fiter value + @Transactional + public Result listProducts(Long cat) { + // Get list of all categories in ascending order + List categories = Category.findAll(); + // Instantiate products, an Array list of products + List products = new ArrayList(); + + if (cat == 0) { + // Get the list of ALL products with filter + products = Product.findAll(); + }else { + products = Category.find.ref(cat).getProducts(); + } + + // Render the list products view, passing parameters + // categories and products lists + // category id - used for filtering + // the filter string - this will be displayed in the filter text input + // current user - if one is logged in + return ok(listProducts.render(products, categories, getCurrentUser(),e)); + } + + @Transactional + public Result addProduct() { + Form addProductForm = formFactory.form(Product.class); + return ok(addProduct.render(addProductForm, getCurrentUser())); + } + @Transactional + public Result addProductSubmit() { + Product newProduct; + String saveImageMsg; + Form newProductForm = formFactory.form(Product.class).bindFromRequest(); + + if (newProductForm.hasErrors()) { + return badRequest(addProduct.render(newProductForm, + getCurrentUser())); + } + else { + newProduct = newProductForm.get(); + + + // Save the object to the Products table in the database + newProduct.save(); + // Get category ids (checked boxes from form) + // Find category objects and set categories list for this product + for (Long cat : newProduct.getCatSelect()) { + newProduct.categories.add(Category.find.byId(cat)); + } + newProduct.update(); + } + MultipartFormData data = request().body().asMultipartFormData(); + FilePart image = data.getFile("upload"); + + saveImageMsg = saveFile(newProduct.getId(), image); + + flash("success", "Product " + newProduct.getName() + " has been created/updated " + saveImageMsg); + + return redirect(controllers.routes.AdminProductCtrl.index()); + } + + + @Transactional + public Result deleteProduct(Long id) { + Product.find.ref(id).delete(); + + flash("success", "Product has been deleted"); + + return redirect(routes.AdminProductCtrl.index()); + } + + + @Transactional + public Result updateProduct(Long id) { + Product p; + Form productForm; + + try { + p = Product.find.byId(id); + productForm = formFactory.form(Product.class).fill(p); + } + catch (Exception ex) { + return badRequest("error"); + } + return ok(updateProduct.render(id, productForm,getCurrentUser())); + } + + @Transactional + public Result updateProductSubmit(Long id) { + String saveImageMsg; + + // Retrieve the submitted form object (bind from the HTTP request) + Form updateProductForm = formFactory.form(Product.class).bindFromRequest(); + + // Check for errors (based on constraints set in the Product class) + if (updateProductForm.hasErrors()) { + // Display the form again by returning a bad request + return badRequest(updateProduct.render(id,updateProductForm, getCurrentUser())); + } else { + // No errors found - extract the product detail from the form + Product p = updateProductForm.get(); + p.setId(id); + + // Get category ids (checked boxes from form) + // Find category objects and set categories list for this product + List newCats = new ArrayList(); + for (Long cat : p.getCatSelect()) { + newCats.add(Category.find.byId(cat)); + } + p.categories = newCats; + //update (save) this product + p.update(); + + MultipartFormData data = request().body().asMultipartFormData(); + FilePart image = data.getFile("upload"); + + saveImageMsg = saveFile(p.getId(), image); + + flash("success", "Product " + p.getName() + " has been created/updated " + saveImageMsg); + + // Redirect to the admin home + return redirect(controllers.routes.AdminProductCtrl.index()); + } + } + + + + public String saveFile(Long id, FilePart uploaded) { + // make sure that the file exists + if (uploaded != null) { + // make sure that the content is indeed an image + String mimeType = uploaded.getContentType(); + if (mimeType.startsWith("image/")) { + // get the file name + String fileName = uploaded.getFilename(); + // save the file object (created without a path, File saves + // the content to a default location, usually the temp or tmp + // directory) + File file = uploaded.getFile(); + // create an ImageMagik operation - this object is used to specify + // the required image processing + IMOperation op = new IMOperation(); + // add the uploaded image to the operationop.addImage(file.getAbsolutePath()); + op.addImage(file.getAbsolutePath()); + // resize the image using height and width saveFileOld(Long id, FilePart uploaded) { + op.resize(300, 200); + // save the image as jpg + op.addImage("public/images/productImages/" + id + ".jpg"); + // create another Image Magick operation and repeat the process above to + // specify how a thumbnail image should be processed - size 60px + IMOperation thumb = new IMOperation(); + thumb.addImage(file.getAbsolutePath()); + thumb.resize(60); + thumb.addImage("public/images/productImages/thumbnails/" + id + ".jpg"); + // we must make sure that the directories exist before running the operations + File dir = new File("public/images/productImages/thumbnails/"); + if (!dir.exists()) { + dir.mkdirs(); + } + // now we create an Image Magick command and execute the operations + ConvertCmd cmd = new ConvertCmd(); + try { + cmd.run(op); + cmd.run(thumb); + } catch(Exception e) { + e.printStackTrace(); + } + return " and image saved"; + } + } + return "/ no file"; + } + public String saveFileOld(Long id, FilePart uploaded) { + // make sure that the file exists + String mimeType = uploaded.getContentType(); + if (uploaded != null) { + // make sure that the content is indeed an image + if (mimeType.startsWith("image/")) { + // get the file name + String fileName = uploaded.getFilename(); + String extension = ""; + int i = fileName.lastIndexOf('.'); + if (i >= 0) { + extension = fileName.substring(i+1); + } + // save the file object (created without a path, File saves + // the content to a default location, usually the temp or tmp + // directory) + File file = uploaded.getFile(); + // we must make sure that the directory for the images exists before we save it + File dir = new File("public/images/productImages"); + if (!dir.exists()) { + dir.mkdirs(); + } + // move the file to the required location (in a real application + // the path to where images are stored would be configurable, but + // for the lab we just hard-code it) + if(file.renameTo(new File("public/images/productImages/", id + "." + extension))) { + return "/ file uploaded"; + } else { + return "/ file upload failed"; + } + } + } + return "/ no file"; + } + + +} \ No newline at end of file diff --git a/app/controllers/ProductCtrl.java b/app/controllers/ProductCtrl.java new file mode 100644 index 0000000..926491f --- /dev/null +++ b/app/controllers/ProductCtrl.java @@ -0,0 +1,83 @@ +package controllers; + +import play.mvc.*; +import play.api.Environment; +import play.data.*; +import play.db.ebean.Transactional; + +import java.util.ArrayList; +import java.util.List; +import javax.inject.Inject; + + +import models.users.*; +import models.products.*; +import views.html.*; + + + +/** + * This controller contains an action to handle HTTP requests + * to the application's home page. + */ +public class ProductCtrl extends Controller { + + /** + * An action that renders an HTML page with a welcome message. + * The configuration in the routes file means that + * this method will be called when the application receives a + * GET request with a path of /. + */ + private FormFactory formFactory; + private Environment e; + + @Inject + public ProductCtrl(FormFactory f,Environment env) { + this.formFactory = f; + this.e = env; + } + // Get a user - if logged in email will be set in the session + @Transactional + public User getCurrentUser() { + User u = User.getLoggedIn(session().get("email")); + return u; + } + public Result index() { + return redirect(routes.ProductCtrl.listProducts(0, "")); + } + + // Get a list of products + // If cat parameter is 0 then return all products + // Otherwise return products for a category (by id) + // In both cases products will be searched using the fiter value + @Transactional + public Result listProducts(Long cat, String filter) { + // Get list of all categories in ascending order + List categories = Category.findAll(); + // Instantiate products, an Array list of products + List products = new ArrayList(); + + if (cat == 0) { + // Get the list of ALL products with filter + products = Product.findAll(filter); + } + else { + // Get products for the selected category and filter (search field) + products = Product.findFilter(cat, filter); + } + // Render the list products view, passing parameters + // categories and products lists + // category id - used for filtering + // the filter string - this will be displayed in the filter text input + // current user - if one is logged in + return ok(listProducts.render(products,categories, cat, filter, getCurrentUser(),e)); + } + public Result productDetails(Long id) { + Product p; + + p = Product.find.byId(id); + + return ok(productDetails.render(p,User.getLoggedIn(session().get("email")),e)); + } + +} \ No newline at end of file diff --git a/app/controllers/security/CheckIfAdmin.java b/app/controllers/security/CheckIfAdmin.java new file mode 100644 index 0000000..8fb5f47 --- /dev/null +++ b/app/controllers/security/CheckIfAdmin.java @@ -0,0 +1,38 @@ +package controllers.security; + +import play.mvc.*; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.CompletableFuture; + +import models.users.*; + +/* - Docs - +https://alexgaribay.com/2014/06/16/authentication-in-play-framework-using-java/ +https://www.playframework.com/documentation/2.2.x/JavaActionsComposition +*/ + +// Check if this is an admin user (before permitting an action) +public class CheckIfAdmin extends Action.Simple { + + // Functional Java which is executed concurrently + // Promise represents a handle for the future result + // Http.Context contains the current request - which will be allowed + // only if the conditions here are met + public CompletionStage call(Http.Context ctx) { + + // Check if current user (in session) is an admin + String id = ctx.session().get("email"); + if (id != null) { + User u = User.getLoggedIn(id); + if ("admin".equals(u.getRole())) { + + // User admin sp continue with the http request + return delegate.call(ctx); + } + } + //Result unauthorized = Results.unauthorized("unauthorized"); + // Unauthorised - redirect to login page + ctx.flash().put("error", "Admin Login Required."); + return CompletableFuture.completedFuture(redirect(routes.LoginCtrl.login())); + } +} \ No newline at end of file diff --git a/app/controllers/security/CheckIfCustomer.java b/app/controllers/security/CheckIfCustomer.java new file mode 100644 index 0000000..4757e1d --- /dev/null +++ b/app/controllers/security/CheckIfCustomer.java @@ -0,0 +1,38 @@ +package controllers.security; + +import play.mvc.*; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.CompletableFuture; + +import models.users.*; + +/* - Docs - +https://alexgaribay.com/2014/06/16/authentication-in-play-framework-using-java/ +https://www.playframework.com/documentation/2.2.x/JavaActionsComposition +*/ + +// Check if this is an admin user (before permitting an action) +public class CheckIfCustomer extends Action.Simple { + + // Functional Java which is executed concurrently + // Promise represents a handle for the future result + // Http.Context contains the current request - which will be allowed + // only if the conditions here are met + public CompletionStage call(Http.Context ctx) { + + // Check if current user (in session) is an admin + String id = ctx.session().get("email"); + if (id != null) { + User u = User.getLoggedIn(id); + if ("customer".equals(u.getRole())) { + + // User admin sp continue with the http request + return delegate.call(ctx); + } + } + //Result unauthorized = Results.unauthorized("unauthorized"); + // Unauthorised - redirect to login page + ctx.flash().put("error", "Login Required."); + return CompletableFuture.completedFuture(redirect(routes.LoginCtrl.login())); + } +} \ No newline at end of file diff --git a/app/controllers/security/LoginCtrl.java b/app/controllers/security/LoginCtrl.java new file mode 100644 index 0000000..8cd2c92 --- /dev/null +++ b/app/controllers/security/LoginCtrl.java @@ -0,0 +1,68 @@ +package controllers.security; + +import play.api.Environment; +import play.mvc.*; +import play.data.*; +import play.db.ebean.Transactional; + +import java.util.ArrayList; +import java.util.List; +import javax.inject.Inject; + +import views.html.*; +import models.users.*; + +public class LoginCtrl extends Controller { + private FormFactory formFactory; + private Environment env; + + @Inject + public LoginCtrl(Environment e, FormFactory f) { + this.env = e; + this.formFactory = f; + } + + public Result login() { + Form loginForm = formFactory.form(Login.class); + + return ok(login.render(loginForm, User.getLoggedIn(session().get("email")))); + } + + public Result loginSubmit() { + // Bind form instance to the values submitted from the form + Form loginForm = formFactory.form(Login.class).bindFromRequest(); + + // Check for errors + // Uses the validate method defined in the Login class + if (loginForm.hasErrors()) { + // If errors, show the form again + return badRequest(login.render(loginForm, User.getLoggedIn(session().get("email")))); + } + else { + // User Logged in successfully + // Clear the existing session + session().clear(); + // Store the logged in email in the session + session("email", loginForm.get().getEmail()); + + // Check user type + User u = User.getLoggedIn(loginForm.get().getEmail()); + // If admin - go to admin section + if (u != null && "admin".equals(u.getRole())) { + return redirect(controllers.routes.AdminProductCtrl.index()); + } + + // Return to home page + return redirect(controllers.routes.ProductCtrl.index()); + } + } + + public Result logout() { + session().clear(); + flash("success", "You've been logged out"); + return redirect(controllers.security.routes.LoginCtrl.login()); + } + + + +} \ No newline at end of file diff --git a/app/controllers/security/Secured.java b/app/controllers/security/Secured.java new file mode 100644 index 0000000..765f08f --- /dev/null +++ b/app/controllers/security/Secured.java @@ -0,0 +1,20 @@ +package controllers; + +import play.*; +import play.mvc.*; +import play.mvc.Http.*; + +import models.*; +import models.users.*; + +public class Secured extends Security.Authenticator { + @Override + public String getUsername(Context ctx) { + return ctx.session().get("email"); + } + + @Override + public Result onUnauthorized(Context ctx) { + return redirect(controllers.security.routes.LoginCtrl.login()); + } +} \ No newline at end of file diff --git a/app/models/products/Category.java b/app/models/products/Category.java new file mode 100644 index 0000000..4382423 --- /dev/null +++ b/app/models/products/Category.java @@ -0,0 +1,77 @@ +package models.products; + +import java.util.*; +import javax.persistence.*; + +import io.ebean.*; +import play.data.format.*; +import play.data.validation.*; + +@Entity +public class Category extends Model { + @Id + private Long id; + + @Constraints.Required + private String name; + + @ManyToMany(cascade = CascadeType.ALL) + private List products; + + public Category() { + } + + public Category(Long id, String name, List products) { + this.id = id; + this.name = name; + this.products = products; + } + + public Long getId() { + return this.id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public List getProducts() { + return products; + } + + public void setProducts(List products) { + this.products = products; + } + + public static Finder find = new Finder(Category.class); + + public static List findAll() { + return Category.find.query().where().orderBy("name asc").findList(); + } + + public static Map options() { + LinkedHashMap options = new LinkedHashMap(); + + for (Category c: Category.findAll()) { + options.put(c.getId().toString(), c.getName()); + } + + return options; + } + // Check if a product is in a category + public static boolean inCategory(Long category, Long product) { + return find.query().where() + .eq("products.id", product) + .eq("id", category) + .findCount() > 0; + } + +} \ No newline at end of file diff --git a/app/models/products/Product.java b/app/models/products/Product.java new file mode 100644 index 0000000..4224ace --- /dev/null +++ b/app/models/products/Product.java @@ -0,0 +1,105 @@ +package models.products; + +import java.util.*; +import javax.persistence.*; + +import io.ebean.*; +import play.data.format.*; +import play.data.validation.*; + +@Entity +public class Product extends Model { + + // Properties + @Id + private Long id; + @Constraints.Required + private String name; + @ManyToMany(cascade = CascadeType.ALL,mappedBy="products") + public List categories; + @Constraints.Required + private String description; + @Constraints.Required + private int stock; + @Constraints.Required + private double price; + + public static final Finder find = new Finder<>(Product.class); + // List of category ids - this will be bound to checkboxes in the view form + private List catSelect = new ArrayList(); + + public static final List findAll() { + + return Product.find.all(); + } + + // Default Constructor + public Product() { + } + + public static List findAll(String filter) { + return Product.find.query().where() + .ilike("name", "%" + filter + "%") + .orderBy("name asc") + .findList(); + } + + + public static List findFilter(Long cat, String filter) { + return Product.find.query().where() + .eq("categories.id", catID) + .ilike("name", "%" + filter + "%") + .orderBy("name asc") + .findList(); + } + + + // Constructor to initialise object + public Product(Long id, String name, String description, int stock, double price) { + this.id = id; + this.name = name; + this.description = description; + this.stock = stock; + this.price = price; + } + + // Accessor methods + 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; + } + + public String getDescription() { + return description; + } + public void setDescription(String description) { + this.description = description; + } + public int getStock() { + return stock; + } + public void setStock(int stock) { + this.stock = stock; + } + public double getPrice() { + return price; + } + public void setPrice(double price) { + this.price = price; + } + public List getCatSelect(){ + return catSelect; + } + public void setCatSelect(List catSelect){ + this.catSelect = catSelect; + } + } + \ No newline at end of file diff --git a/app/models/users/Administrator.java b/app/models/users/Administrator.java new file mode 100644 index 0000000..4cd20fb --- /dev/null +++ b/app/models/users/Administrator.java @@ -0,0 +1,26 @@ +package models.users; + +import java.util.*; +import javax.persistence.*; + +import io.ebean.*; +import play.data.format.*; +import play.data.validation.*; + +@Entity +// This is a User of type admin +@DiscriminatorValue("admin") + +// Administrator inherits from the User class +public class Administrator extends User{ + + public Administrator() { + + } + + public Administrator(String email, String role, String name, String password) + { + super(email, role, name, password); + } + +} \ No newline at end of file diff --git a/app/models/users/Customer.java b/app/models/users/Customer.java new file mode 100644 index 0000000..b31916a --- /dev/null +++ b/app/models/users/Customer.java @@ -0,0 +1,75 @@ +package models.users; + +import java.util.*; +import javax.persistence.*; + +import io.ebean.*; +import play.data.format.*; +import play.data.validation.*; + + +@Entity + +// This is a user of type Customer +@DiscriminatorValue("customer") + +// Customer inherits from the User class +public class Customer extends User{ + + private String street1; + private String street2; + private String town; + private String postCode; + private String creditCard; + + public Customer(String email, String role, String name, String password, String street1, String street2, String town, String postCode, String creditCard) + { + super(email, role, name, password); + this.street1 = street1; + this.street2 = street2; + this.town = town; + this.postCode = postCode; + this.creditCard = creditCard; + } + + public String getStreet1() { + return street1; + } + + public void setStreet1(String street1) { + this.street1 = street1; + } + + public String getStreet2() { + return street2; + } + + public void setStreet2(String street2) { + this.street2 = street2; + } + + public String getTown() { + return town; + } + + public void setTown(String town) { + this.town = town; + } + + public String getPostCode() { + return postCode; + } + + public void setPostCode(String postCode) { + this.postCode = postCode; + } + + public String getCreditCard() { + return creditCard; + } + + public void setCreditCard(String creditCard) { + this.creditCard = creditCard; + } + +} \ No newline at end of file diff --git a/app/models/users/Login.java b/app/models/users/Login.java new file mode 100644 index 0000000..2ea0893 --- /dev/null +++ b/app/models/users/Login.java @@ -0,0 +1,33 @@ +package models.users; + +public class Login { + private String email; + private String password; + + // Validate method - invoked during error checking + // after form based on a Login object has been submitted + public String validate() { + + // Call the static authenticate method in User + if (User.authenticate(email, password) == null) { + return "Invalid user or password"; + } + return null; + } + + public String getEmail() { + return email; + } + + public String getPassword() { + return password; + } + + public void setEmail(String email) { + this.email = email; + } + + public void setPassword(String password) { + this.password = password; + } +} \ No newline at end of file diff --git a/app/models/users/Manager.java b/app/models/users/Manager.java new file mode 100644 index 0000000..0d15d22 --- /dev/null +++ b/app/models/users/Manager.java @@ -0,0 +1,36 @@ +package models.users; + +import java.util.*; +import javax.persistence.*; + +import io.ebean.*; +import play.data.format.*; +import play.data.validation.*; + +@Entity +// This is a User of type manager + +@DiscriminatorValue("manager") + +// Manager inherits from the User class +public class Manager extends User { + + private String department; + + public Manager() { + + } + public Manager(String email, String role, String name, String password, String department) + { + super(email, role, name, password); + this.department = department; + } + + public String getDepartment() { + return department; + } + + public void setDepartment(String department) { + this.department = department; + } +} \ No newline at end of file diff --git a/app/models/users/User.java b/app/models/users/User.java new file mode 100644 index 0000000..6c94ab8 --- /dev/null +++ b/app/models/users/User.java @@ -0,0 +1,97 @@ +package models.users; + +import java.util.*; +import javax.persistence.*; + +import io.ebean.*; +import play.data.format.*; +import play.data.validation.*; + +@Entity +//Specified mapped table name +@Table(name = "user") +//Map inherited class to a single table +@Inheritance(strategy=InheritanceType.SINGLE_TABLE) +//Discriminator column used to define user type +@DiscriminatorColumn(name="role") +//The user type is user +@DiscriminatorValue("user") +public class User extends Model { + @Id + private String email; + + @Constraints.Required + private String role; + + @Constraints.Required + private String name; + + @Constraints.Required + private String password; + + public User() { + } + // Constructor to initialise object + public User(String email, String role, String name, String password) { + this.email = email; + this.role = role; + this.name = name; + this.password = password; + } + + public String getEmail() { + return email; + } + + public String getRole() { + return role; + } + + public String getName() { + return name; + } + + public String getPassword() { + return password; + } + + public void setEmail(String email) { + this.email = email; + } + + public void setRole(String role) { + this.role = role; + } + + + public void setName(String name) { + this.name = name; + } + + + public void setPassword(String password) { + this.password = password; + } + + public static Finder find = new Finder(User.class); + + public static List findAll() { + return User.find.all(); + } + + public static User authenticate(String email, String password) { + return find.query().where().eq("email", email).eq("password", password).findUnique(); + } + + public static User getLoggedIn(String id) { + if (id == null) { + return null; + } + else { + return find.byId(id); + } + } + + + +} \ No newline at end of file diff --git a/app/views/listProducts.scala.html b/app/views/listProducts.scala.html new file mode 100644 index 0000000..64fc5bd --- /dev/null +++ b/app/views/listProducts.scala.html @@ -0,0 +1,72 @@ +@import models.products.Category +@import models.products.Product +@import models.users.User +@(products: List[Product], categories: List[Category], user: User,env: play.api.Environment) + + +@main("Products",user) { + +

Product Catalogue

+
+
+
+

Categories

+
+ All Categories + @for(c <- categories) { + @c.getName + @c.getProducts.size() + + } +
+
+
+ @if(flash.containsKey("success")) { +
+ @flash.get("success") +
+ } + +
+
+ + +
+
+ + + + + + + + + + + + + + + @for(p<-products) { + + @if(env.resource("public/images/productImages/thumbnails/" + p.getId + ".jpg").isDefined) { + + } else { + + } + + + + + + + + + } + + +
IDNameCategoryDescriptionStockPrice
@p.getId + @p.getName@p.getDescription@p.getStock€ @("%.2f".format(p.getPrice))
+
+
+} \ No newline at end of file diff --git a/app/views/login.scala.html b/app/views/login.scala.html new file mode 100644 index 0000000..09bd469 --- /dev/null +++ b/app/views/login.scala.html @@ -0,0 +1,38 @@ +@import models.users.User +@import models.users.Login +@(loginForm: Form[Login], user: User) +@import helper._ + +@main("Login", user) { +

Product Catalogue

+
+

Sign in

+ @if(loginForm.hasGlobalErrors) { +

+ @loginForm.globalError.message; +

+ } + @if(flash.containsKey("error")) { +

+ @flash.get("loginRequired") +

+ } + + + @helper.form(controllers.security.routes.LoginCtrl.loginSubmit()) { + @CSRF.formField + +
+ @inputText(loginForm("email"), '_label -> "", + 'class -> "form-control input-xs", 'placeholder -> "Email") +
+
+ @inputPassword(loginForm("password"), '_label -> "", + 'class -> "form-control input-xs", 'placeholder -> "Password") +
+
+ +
+ } +
+} \ No newline at end of file diff --git a/app/views/main.scala.html b/app/views/main.scala.html new file mode 100644 index 0000000..5f38e28 --- /dev/null +++ b/app/views/main.scala.html @@ -0,0 +1,72 @@ +@(title: String, user: models.users.User )(content: Html) + + + + + + + + Online Shop - @title + + + + + + + + + + + + +
+ @content +
+
+
+
+ +
+ +
+ Copyright + Online Shop +
+
+
+
+ + + + \ No newline at end of file diff --git a/app/views/productAdmin/addProduct.scala.html b/app/views/productAdmin/addProduct.scala.html new file mode 100644 index 0000000..6cc9d51 --- /dev/null +++ b/app/views/productAdmin/addProduct.scala.html @@ -0,0 +1,39 @@ +@import models.products.Category +@import models.products.Product +@import models.users.User +@(productForm: Form[Product], user: User) +@import helper._ + +@main("Add Product",user) { +

Add a new product

+ @form(action=routes.AdminProductCtrl.addProductSubmit(), 'class -> "form-horizontal", 'role -> "form",'enctype -> "multipart/form-data") { + @* CSRF attack prevention *@ + @CSRF.formField + @inputText(productForm("name"), '_label -> "Name", 'class -> "form-control") + + + + + + @for((value, name) <- Category.options) { + @name
+ } + @inputText(productForm("description"), '_label -> "Description", 'class -> "form-control") + @inputText(productForm("stock"), '_label -> "Stock", 'class -> "form-control") + @inputText(productForm("price"), '_label -> "Price", 'class -> "form-control") + + @inputText(productForm("id"), '_label -> "", 'hidden -> "hidden") + + + +

+ + } +} \ No newline at end of file diff --git a/app/views/productAdmin/listProducts.scala.html b/app/views/productAdmin/listProducts.scala.html new file mode 100644 index 0000000..86e182c --- /dev/null +++ b/app/views/productAdmin/listProducts.scala.html @@ -0,0 +1,80 @@ + +@import models.products.Category +@import models.products.Product +@import models.users.User +@(products: List[Product], categories: List[Category], catId: Long, filter: String, user: User,env: play.api.Environment) + +@main("Products",user) { + +

Product Catalogue

+
+
+
+

Categories

+
+ All Categories + @for(c <- categories) { + @c.getName + @c.getProducts.size() + + } +
+
+
+ + @if(flash.containsKey("success")) { +
+ @flash.get("success") +
+ } + + + + + + + + + + + + + + @for(p<-products) { + + @if(env.resource("public/images/productImages/thumbnails/" + p.getId + ".jpg").isDefined) { + + } else { + + } + + + + + + + + + + } + + +
ImageIDNameDescriptionStockPrice
@p.getId + @p.getName@p.getDescription@p.getStock€ @("%.2f".format(p.getPrice)) + + + + + + + +
+ +

+ + + +

+
+
+} \ No newline at end of file diff --git a/app/views/productAdmin/main.scala.html b/app/views/productAdmin/main.scala.html new file mode 100644 index 0000000..c2565d4 --- /dev/null +++ b/app/views/productAdmin/main.scala.html @@ -0,0 +1,75 @@ +@import models.users.User +@(title: String, user: User )(content: Html) + + + + + + + + Online Shop - @title + + + + + + + + + + + + +
+ @content +
+
+
+
+ +
+ +
+ Copyright + Online Shop +
+
+
+
+ + + + diff --git a/app/views/productAdmin/updateProduct.scala.html b/app/views/productAdmin/updateProduct.scala.html new file mode 100644 index 0000000..4523a39 --- /dev/null +++ b/app/views/productAdmin/updateProduct.scala.html @@ -0,0 +1,42 @@ +@import models.products.Product +@import models.products.Category +@import models.users.User +@(id: Long, updateProductForm: Form[Product], user: User) +@import helper._ +@main("Update product", user){ +

Update Product

+ +@form(action=routes.AdminProductCtrl.updateProductSubmit(id), 'class -> "form-horizontal", +'role -> "form",'enctype -> "multipart/form-data") { + @* CSRF attack prevention *@ + @CSRF.formField + @inputText(updateProductForm("name"), '_label -> "Name", 'class -> "form-control") + @inputText(updateProductForm("description"), '_label -> "Description", 'class -> "form-control") + + + + + + @for((value, name) <- Category.options) { + @name
+ } + + @inputText(updateProductForm("stock"), '_label -> "Stock", 'class -> "form-control") + @inputText(updateProductForm("price"), '_label -> "Price", 'class -> "form-control") + + + +

+ + + } +} diff --git a/app/views/productDetails.scala.html b/app/views/productDetails.scala.html new file mode 100644 index 0000000..0021926 --- /dev/null +++ b/app/views/productDetails.scala.html @@ -0,0 +1,42 @@ +@import models.products.Product +@import models.users.User +@(p: Product,user: User,env: play.api.Environment) + + +@main("Full Image", user) { + + +
+ + @if(flash.containsKey("success")) { +
+ @flash.get("success") +
+ } + + + + + + + + + + + @if(env.resource("public/images/productImages/" + p.getId + ".jpg").isDefined) { + + } else { + + } + + + + + + +
ImageID
@p.getId
+ + +
+ +} \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..de0d305 --- /dev/null +++ b/build.gradle @@ -0,0 +1,41 @@ +plugins { + id 'play' + id 'idea' +} + +def playVersion = '2.6.11' +def scalaVersion = System.getProperty("scala.binary.version", /* default = */ "2.12") + +model { + components { + play { + platform play: playVersion, scala: scalaVersion, java: '1.8' + injectedRoutesGenerator = true + + sources { + twirlTemplates { + defaultImports = TwirlImports.JAVA + } + } + } + } +} + +dependencies { + play "com.typesafe.play:play-guice_$scalaVersion:$playVersion" + play "com.typesafe.play:play-logback_$scalaVersion:$playVersion" + play "com.typesafe.play:filters-helpers_$scalaVersion:$playVersion" +} + +repositories { + jcenter() + maven { + name "lightbend-maven-releases" + url "https://repo.lightbend.com/lightbend/maven-release" + } + ivy { + name "lightbend-ivy-release" + url "https://repo.lightbend.com/lightbend/ivy-releases" + layout "ivy" + } +} diff --git a/build.sbt b/build.sbt new file mode 100644 index 0000000..fdae952 --- /dev/null +++ b/build.sbt @@ -0,0 +1,16 @@ +name := """lab3""" +organization := "com.example" + +version := "1.0-SNAPSHOT" + +lazy val root = (project in file(".")).enablePlugins(PlayJava, PlayEbean) + +scalaVersion := "2.12.4" + +libraryDependencies += guice + +// include the H2 Dependency +libraryDependencies += "com.h2database" % "h2" % "1.4.192" +// Load dependencies +libraryDependencies ++= Seq(evolutions, jdbc) + diff --git a/conf/application.conf b/conf/application.conf new file mode 100644 index 0000000..2b13b7a --- /dev/null +++ b/conf/application.conf @@ -0,0 +1,24 @@ +# This is the main configuration file for the application. +# https://www.playframework.com/documentation/latest/ConfigFile +play.filters { +hosts { +} +headers { + contentSecurityPolicy = null +} +cors { + allowedOrigins = null +} +} +db { + default.driver=org.h2.Driver + + # DB file on disk + default.url="jdbc:h2:file:./data/productsDB" + + default.username = sa + default.password = "" +} + +ebean.default=["models.*"] + diff --git a/conf/evolutions/default/1.sql b/conf/evolutions/default/1.sql new file mode 100644 index 0000000..9963f69 --- /dev/null +++ b/conf/evolutions/default/1.sql @@ -0,0 +1,63 @@ +# --- Created by Ebean DDL +# To stop Ebean DDL generation, remove this comment and start using Evolutions + +# --- !Ups + +create table category ( + id bigint auto_increment not null, + name varchar(255), + constraint pk_category primary key (id) +); + +create table category_product ( + category_id bigint not null, + product_id bigint not null, + constraint pk_category_product primary key (category_id,product_id) +); + +create table product ( + id bigint auto_increment not null, + name varchar(255), + description varchar(255), + stock integer not null, + price double not null, + constraint pk_product primary key (id) +); + +create table user ( + role varchar(255), + email varchar(255) not null, + name varchar(255), + password varchar(255), + department varchar(255), + street1 varchar(255), + street2 varchar(255), + town varchar(255), + post_code varchar(255), + credit_card varchar(255), + constraint pk_user primary key (email) +); + +alter table category_product add constraint fk_category_product_category foreign key (category_id) references category (id) on delete restrict on update restrict; +create index ix_category_product_category on category_product (category_id); + +alter table category_product add constraint fk_category_product_product foreign key (product_id) references product (id) on delete restrict on update restrict; +create index ix_category_product_product on category_product (product_id); + + +# --- !Downs + +alter table category_product drop constraint if exists fk_category_product_category; +drop index if exists ix_category_product_category; + +alter table category_product drop constraint if exists fk_category_product_product; +drop index if exists ix_category_product_product; + +drop table if exists category; + +drop table if exists category_product; + +drop table if exists product; + +drop table if exists user; + diff --git a/conf/evolutions/default/2.sql b/conf/evolutions/default/2.sql new file mode 100644 index 0000000..005ad4a --- /dev/null +++ b/conf/evolutions/default/2.sql @@ -0,0 +1,44 @@ +# --- Sample dataset + +# --- !Ups + +delete from product; +delete from category; + +insert into category (id,name) values ( 1,'Audio' ); +insert into category (id,name) values ( 2,'Books' ); +insert into category (id,name) values ( 3,'Computer' ); +insert into category (id,name) values ( 4,'Furniture' ); +insert into category (id,name) values ( 5,'Kitchen' ); +insert into category (id,name) values ( 6,'Laundry' ); +insert into category (id,name) values ( 7,'Mobile Phone' ); +insert into category (id,name) values ( 8,'Television' ); + +insert into product (id,name,description,stock,price) values ( 1,'Kettle','Steel Electric Kettle',100,55.00 ); +insert into product (id,name,description,stock,price) values ( 2,'Fridge freezer','Fridge + freezer large',45,799.00 ); +insert into product (id,name,description,stock,price) values ( 3,'Portable Music Player','250GB music player (MP3,MP4,WMA,WAV)',5,99.00 ); +insert into product (id,name,description,stock,price) values ( 4,'13inch Laptop','HP laptop,8GB RAM,250GB SSD',45,799.00 ); +insert into product (id,name,description,stock,price) values ( 5,'8inch Tablet','Android 5.1 Tablet,32GB storage,8inch screen',5,99.00 ); +insert into product (id,name,description,stock,price) values ( 6,'46inch TV','Sony 4K,OLED,Smart TV',12,2799.00 ); +insert into product (id,name,description,stock,price) values ( 7,'Washing Machine','1600rpm spin,A+++ rated,10KG',50,699.00 ); +insert into product (id,name,description,stock,price) values ( 8,'Phone','Windows 10,5.2inch OLED,3GB RAM,64GB Storage',45,799.00 ); +insert into product (id,name,description,stock,price) values ( 9,'10inch Tablet','Windows 10,128GB storage,8inch screen',5,299.00 ); +insert into product (id,name,description,stock,price) values ( 10,'Oven','Oven + Grill,Stainless Steel',10,399.00 ); +insert into product (id,name,description,stock,price) values ( 11,'Bed','Super King size,super comfort mattress',5,899.00 ); +insert into product (id,name,description,stock,price) values ( 12,'Learning JavaScript','Become a JavaScript expert in 2 hours!',50,29.00 ); + +insert into category_product (category_id,product_id) values (5,1); +insert into category_product (category_id,product_id) values (5,2); +insert into category_product (category_id,product_id) values (1,3); +insert into category_product (category_id,product_id) values (3,4); +insert into category_product (category_id,product_id) values (3,5); +insert into category_product (category_id,product_id) values (8,6); +insert into category_product (category_id,product_id) values (6,7); +insert into category_product (category_id,product_id) values (7,8); +insert into category_product (category_id,product_id) values (3,9); +insert into category_product (category_id,product_id) values (5,10); +insert into category_product (category_id,product_id) values (4,11); +insert into category_product (category_id,product_id) values (2,12); +insert into category_product (category_id,product_id) values (5,7); +insert into category_product (category_id,product_id) values (3,8); +insert into category_product (category_id,product_id) values (3,3); diff --git a/conf/evolutions/default/3.sql b/conf/evolutions/default/3.sql new file mode 100644 index 0000000..1341870 --- /dev/null +++ b/conf/evolutions/default/3.sql @@ -0,0 +1,8 @@ +# --- !Ups +delete from user; + +insert into user (email,name,password,role) values ( 'admin@products.com', 'Alice Admin', 'password', 'admin' ); + +insert into user (email,name,password,role) values ( 'manager@products.com', 'Bob Manager', 'password', 'manager' ); + +insert into user (email,name,password,role) values ( 'customer@products.com', 'Charlie Customer', 'password', 'customer' ); \ No newline at end of file diff --git a/conf/logback.xml b/conf/logback.xml new file mode 100644 index 0000000..86ec12c --- /dev/null +++ b/conf/logback.xml @@ -0,0 +1,41 @@ + + + + + + + ${application.home:-.}/logs/application.log + + %date [%level] from %logger in %thread - %message%n%xException + + + + + + %coloredLevel %logger{15} - %message%n%xException{10} + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/conf/routes b/conf/routes new file mode 100644 index 0000000..d05fb0d --- /dev/null +++ b/conf/routes @@ -0,0 +1,33 @@ +# Routes +# This file defines all application routes (Higher priority routes first) +# ~~~~ + +# An example controller showing a sample home page +GET / controllers.ProductCtrl.index() + +# Show a list of products - note optional parameter + +GET /listProducts controllers.ProductCtrl.listProducts(cat:Long ?= 0, filter ?= "") +GET /productDetails/:id controllers.ProductCtrl.productDetails(id:Long) + +# Login form +GET /login controllers.security.LoginCtrl.login() +POST /login controllers.security.LoginCtrl.loginSubmit() +GET /logout controllers.security.LoginCtrl.logout() + + +# Product Administration +GET /Admin controllers.AdminProductCtrl.index() + +GET /Admin/listProducts controllers.AdminProductCtrl.listProducts(cat: Long ?= 0L) +GET /Admin/listProducts/:cat controllers.AdminProductCtrl.listProducts(cat: Long) + +GET /Admin/addProduct controllers.AdminProductCtrl.addProduct() +POST /Admin/addProductSubmit controllers.AdminProductCtrl.addProductSubmit() + +GET /Admin/updateProduct/:id controllers.AdminProductCtrl.updateProduct(id:Long) +POST /Admin/updateProductSubmit/:id controllers.AdminProductCtrl.updateProductSubmit(id:Long) + +GET /Admin/deleteProduct/:id controllers.AdminProductCtrl.deleteProduct(id:Long) +# Map static resources from the /public folder to the /assets URL path +GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset) diff --git a/data/productsDB.mv.db b/data/productsDB.mv.db new file mode 100644 index 0000000000000000000000000000000000000000..521ef2a9c74a08a086f4836dad0db21a459913cc GIT binary patch literal 61440 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

<5G2M1WZP5 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