From f4db333a04963a04826773f98bdd9e730bab32e9 Mon Sep 17 00:00:00 2001 From: hussainjg Date: Tue, 8 Apr 2025 17:22:26 +0300 Subject: [PATCH 1/7] Initial commit --- pom.xml | 28 ++++++++++----- .../spring/ordering/HelloWorldController.kt | 35 +++++++++++++++++++ .../coded/spring/ordering/OrderController.kt | 32 +++++++++++++++++ .../com/coded/spring/ordering/UsersOrder.kt | 25 +++++++++++++ .../coded/spring/ordering/UsersRepository.kt | 19 ++++++++++ 5 files changed, 131 insertions(+), 8 deletions(-) create mode 100644 src/main/kotlin/com/coded/spring/ordering/HelloWorldController.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/OrderController.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/UsersOrder.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/UsersRepository.kt diff --git a/pom.xml b/pom.xml index 163ad53..716c806 100644 --- a/pom.xml +++ b/pom.xml @@ -1,6 +1,6 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 org.springframework.boot @@ -8,11 +8,11 @@ 3.4.4 - com.coded.spring - Ordering + com.hussain + helloworld 0.0.1-SNAPSHOT - Kotlin.SpringbootV2 - Kotlin.SpringbootV2 + helloworld + My First Spring Boot @@ -33,11 +33,11 @@ org.springframework.boot - spring-boot-starter-web + spring-boot-starter - com.fasterxml.jackson.module - jackson-module-kotlin + org.springframework.boot + spring-boot-starter-web org.jetbrains.kotlin @@ -58,6 +58,18 @@ kotlin-test-junit5 test + + jakarta.inject + jakarta.inject-api + + + org.springframework.boot + spring-boot-starter-data-jpa + + + com.h2database + h2 + diff --git a/src/main/kotlin/com/coded/spring/ordering/HelloWorldController.kt b/src/main/kotlin/com/coded/spring/ordering/HelloWorldController.kt new file mode 100644 index 0000000..40dbcce --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/HelloWorldController.kt @@ -0,0 +1,35 @@ +package com.coded.spring.ordering + +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RestController + +@RestController +class HelloWorldController(val usersRepository: UsersRepository){ + +// Welcome to Online Ordering exercise 1 + @GetMapping("/hello") + fun helloWorld() = "Hello World" + + @PostMapping("/message") + fun printMyMessage(@RequestBody request: PrintMyMessageRequest): String { + return "your name is ${request.name} and civilId is ${request.civilId}" + } + + @PostMapping("/my-name") + fun sayMyName( @RequestBody request: SayMyNameRequest): String { + usersRepository.save(User(name = request.name)) + return "Welcome ${request.name} !" + } + + @GetMapping("/users") + fun getAllUsers(): List = usersRepository.findAll() +} +data class SayMyNameRequest( + val name: String +) +data class PrintMyMessageRequest( + val name: String, + val civilId: String +) \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/OrderController.kt b/src/main/kotlin/com/coded/spring/ordering/OrderController.kt new file mode 100644 index 0000000..f5ade83 --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/OrderController.kt @@ -0,0 +1,32 @@ +package com.coded.spring.ordering + +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RestController + + +@RestController // Optional: makes your API cleaner +class OrderController(val orderRepository: OrderRepository) { + + @PostMapping("/orders") + fun submitOrder(@RequestBody request: OrderRequest): Order { + val order = Order( + username = request.username, + resturant = request.resturant, + items = request.items + ) + return orderRepository.save(order) + } + + @GetMapping("/listOrders") + fun listOrders(): List { + return orderRepository.findAll() + } +} + +data class OrderRequest( + val username: String, + val resturant: String, + val items: List +) \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/UsersOrder.kt b/src/main/kotlin/com/coded/spring/ordering/UsersOrder.kt new file mode 100644 index 0000000..d26d670 --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/UsersOrder.kt @@ -0,0 +1,25 @@ +package com.coded.spring.ordering + +import jakarta.persistence.* +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.stereotype.Repository + +@Repository +interface OrderRepository : JpaRepository + +@Entity +@Table(name = "orders") +data class Order( + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + val id: Long? = null, + val username: String, + val resturant: String, + + @ElementCollection + @CollectionTable(name = "order_items", joinColumns = [JoinColumn(name = "order_id")]) + @Column(name = "item") + val items: List +) { + constructor() : this(null, "", "", emptyList()) +} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/UsersRepository.kt b/src/main/kotlin/com/coded/spring/ordering/UsersRepository.kt new file mode 100644 index 0000000..916bdeb --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/UsersRepository.kt @@ -0,0 +1,19 @@ +package com.coded.spring.ordering + +import jakarta.inject.Named +import jakarta.persistence.* +import org.springframework.data.jpa.repository.JpaRepository + +@Named +interface UsersRepository : JpaRepository + +@Entity +@Table(name = "users") +data class User( + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + var id: Long? = null, + var name: String +){ + constructor(resturant: String, user: String, items: String) : this(null, "") +} \ No newline at end of file From b24de60ba8708c8588c1d4c0dbe2c7eaa9b6717c Mon Sep 17 00:00:00 2001 From: hussainjg Date: Fri, 11 Apr 2025 11:12:56 +0300 Subject: [PATCH 2/7] I have changed all the files --- .DS_Store | Bin 0 -> 6148 bytes pom.xml | 4 ++ src/.DS_Store | Bin 0 -> 6148 bytes src/main/.DS_Store | Bin 0 -> 6148 bytes src/main/kotlin/.DS_Store | Bin 0 -> 6148 bytes src/main/kotlin/com/.DS_Store | Bin 0 -> 6148 bytes src/main/kotlin/com/coded/.DS_Store | Bin 0 -> 6148 bytes src/main/kotlin/com/coded/spring/.DS_Store | Bin 0 -> 6148 bytes .../spring/ordering/HelloWorldController.kt | 35 ------------------ .../coded/spring/ordering/OrderController.kt | 32 ---------------- .../com/coded/spring/ordering/UsersOrder.kt | 25 ------------- .../coded/spring/ordering/UsersRepository.kt | 19 ---------- .../ordering/controller/ItemController.kt | 22 +++++++++++ .../ordering/controller/OrderController.kt | 20 ++++++++++ .../ordering/controller/UserController.kt | 20 ++++++++++ .../com/coded/spring/ordering/model/Item.kt | 19 ++++++++++ .../com/coded/spring/ordering/model/Order.kt | 15 ++++++++ .../com/coded/spring/ordering/model/User.kt | 14 +++++++ .../ordering/repository/ItemRepository.kt | 6 +++ .../ordering/repository/OrderRepository.kt | 6 +++ .../ordering/repository/UserRepository.kt | 6 +++ .../spring/ordering/service/ItemService.kt | 19 ++++++++++ .../spring/ordering/service/OrderService.kt | 19 ++++++++++ .../spring/ordering/service/UserService.kt | 11 ++++++ src/main/resources/application.properties | 6 +++ 25 files changed, 187 insertions(+), 111 deletions(-) create mode 100644 .DS_Store create mode 100644 src/.DS_Store create mode 100644 src/main/.DS_Store create mode 100644 src/main/kotlin/.DS_Store create mode 100644 src/main/kotlin/com/.DS_Store create mode 100644 src/main/kotlin/com/coded/.DS_Store create mode 100644 src/main/kotlin/com/coded/spring/.DS_Store delete mode 100644 src/main/kotlin/com/coded/spring/ordering/HelloWorldController.kt delete mode 100644 src/main/kotlin/com/coded/spring/ordering/OrderController.kt delete mode 100644 src/main/kotlin/com/coded/spring/ordering/UsersOrder.kt delete mode 100644 src/main/kotlin/com/coded/spring/ordering/UsersRepository.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/controller/ItemController.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/controller/OrderController.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/controller/UserController.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/model/Item.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/model/Order.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/model/User.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/repository/ItemRepository.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/repository/OrderRepository.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/repository/UserRepository.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/service/ItemService.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/service/OrderService.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/service/UserService.kt diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..dff2667ee4f6c9c06c77b6cdecd76332e5f2b16e GIT binary patch literal 6148 zcmeHK%}T>S5Z-O8O({YS3Oz1(E!f(k7B3;z7cim+m718M!I&*cYYwH5v%Zi|;`2DO zy8(+ii`W_1{pNQ!`$6`HF~;3R*k{aUj9JhSIVu%`?#fWjBqMShBbx=W48ZybW+wL6 z0l&S@GM2K3ApidTag@z_y-!}NH@3E$R?})*cixlCy}3VMWUimypmix_9F)2rTt(A- zV(*^GWbQ}FG*tyrIE9qk>nI6j?#e|HW~$cH0jp)TCU$4J9QKd9VlX;cb;WXY*z1bn z;ApjKS$q2jrx%mw_$85VnobUEE7>tv!aFEtHLqTp#4>pVPnlh25fTH$05L!eY&HYt zT(H`kO#`i-7$62J7{L8OKtps478=#o0UchSG2TE#0Uh5Gh{B*_u+Rt*5UxuBbtyMb z46e(;FHD|eu+XT>8CNsIIA-SZ@xs;Y;1?>LaYrNd!~ij{&Olw8HlF|I@XJ&_^4Ckq zA_jf7i!x{HkLBT6E1=y&L&3ZP6%f$ZE&*WRKGIP^9T%uWo@21kh@+ri Rl>^d6KoLS6G4Klvd;#FtNsRyi literal 0 HcmV?d00001 diff --git a/pom.xml b/pom.xml index 716c806..8186cd9 100644 --- a/pom.xml +++ b/pom.xml @@ -70,6 +70,10 @@ com.h2database h2 + + org.postgresql + postgresql + diff --git a/src/.DS_Store b/src/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..78928e5ea5732513dcc37ad4c9fbb6864610b875 GIT binary patch literal 6148 zcmeHK%}T>S5Z-O0O({YS3Oz1(E!f(k7B3;z7cim+m70*E!8BW%)*MP9XMG``#OHBl zcOw?-Rm9G~?l-@?*$=Wmj4|%bqYh&ZW6Xwz$Wd7%=w2JDm}EqbV}yA&2@@HD{bpi+ z9q`*NHf8~fS^D++!$}fnvv&KPSE|<5cFnHY4g1c2l(|0(X7kJorZ;F^N|}VE9)wr% zC?7hzXEL1yaXOl+f;bvM%I$TWMl$#0JdH9{>+67Bx9dZvxmff%$1TzApDbHq(LZdr zM6Y|aT-NQq{e#ns;ZrhB<%=ei1K&z^43_W;%IA8X{b`!W^Z|Tjewjx|3=jjv05Pz+ z445;)Zfq_Ev~psA82Et!+#duqMAu-UQEeU2;q@8g79tAh_?AEv23>=NMu>oLT?(j6 zxp`u6T@HR>@?3+3MqSRhni5bB75Utr(^m(WU3 literal 0 HcmV?d00001 diff --git a/src/main/.DS_Store b/src/main/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..a627e920e51cb7f16362ac2992e4293f6836df3e GIT binary patch literal 6148 zcmeHK%}T>S5Z-O8O({YS3Oz1(E!f(k7B3;z7cim+m70*Ep)p(9)Er77XMG``#OHBl zcXJ2^youNu*!^bbXE*af_J=XX-Bs9U%w~*P&=5H)6@unUSIqmvwFYa)3EoB@O zx*yy`(`;hzU&ti&qhz{J2~jwOko(&x31#NWRT3^$uBRPV%W6&R&U!uUpLWGybhhb= z_2{_Q6~n>FX4A3`4v)^SCbRe@k#Cwv4xB65Gg!boD5aWSy+sns zrt*F$eggRp27Z~^gQN2t{ literal 0 HcmV?d00001 diff --git a/src/main/kotlin/.DS_Store b/src/main/kotlin/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..53a9e076fa9d47cbd1b4c9e3b1740a2940ac92c7 GIT binary patch literal 6148 zcmeHK%}T>S5Z<-brW7Fug&r5Y7Hn-%i%uMXB z1AcprJu=CrLH_;w<0#F#-A}$%t8ec#tcKOH?!9N3dzqgtQrDl~qID%@9F)2rTt}09 zZ10`RB=e(WGFJsrIDwSAn$98+U9P~~)qCY%cb;NRb)a{5t z|9G`(TKflwXP4ubc$&yJO(zGomFyZU;T;sSnpbb0#4>pTPnlh25fTH$05L!eY&HYt zT(DZ3O#`i-7$62J7{L8OKtps478=#o0UchSF8CNsIIA-SZ@xs;Y;1?>LaYrNd!~ij{&Ol9@HlF_%@XJ&_^4Ckq zA_jkGzo!i!x{HkLBT6E1*3^d6KoLS6G4Klvd;vS5Z<+|O({YS3Oz1(E!f(k7B3;z7cim+mD-q~!I&*gY7eE5v%Zi|;`2DO zyMY#iM-e*%yWi~m>}Ed5{xHV4I}5su*^Ds@8X`xfM9^I7+A_h2T+I>q^K|0J(l43j zZ<_GiYwUqZ7O;@5e*cF*iK8^@bUyi3rCQsrTXm~x-FZ)P?q%a_mb&BV4UR6QjQv6% z`&UsoAKANSGRekK5>8b@6oe3RdmSZ#oV#+C1gXmPw8Lsxjgj42Ec)H!w&)E`mTj>Z z9Cq5G-#c0^8`j?b!Rf{5IetmxnK*M2-YH_h$JKihyh}N z7}!h(%z0onH?w@IniwDkeqaFi2LTPyF_>#qTL*M_eMWy35e0O7OCSn^j=@|bctE&L z1=OkBJTbUV2fHwFj=@}`PG?-L4D*WG0~VBiZ`u1c~1 literal 0 HcmV?d00001 diff --git a/src/main/kotlin/com/coded/.DS_Store b/src/main/kotlin/com/coded/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..0e597ff43d1419505a291c641d213b1929ed3fb8 GIT binary patch literal 6148 zcmeHK%}T>S5Z-O8-BN@e6nb3nTClZ6EnY&bFJMFuDm5Xc24l7~tvQrJ&iX<=iO=KA z?&c6IcoVTRu=~x<&u->}>R@Pb%{k{$iQB{`?L{*Gk1f zq5Hv2G|9%T{R@>W{3w~sbwU(QAmsiwNJ&OgrgHo#L)te`=N~T~ha*9|&Vt^PR z28e;}W5AvTqPcygQ^mvpG4KNexIai}h>peFpx!#5!|OBpYltYI<68nzT68St2EhZu zO)8*C<@SleO*+`6jdLvK22DESdS#f$u3S7`xLzIXQin6{7^I#UAO^||RL!u3=l>=A zG8-TH@v^M?0&D>Us1QLkM@wz%MZH1+q3x8vp = usersRepository.findAll() -} -data class SayMyNameRequest( - val name: String -) -data class PrintMyMessageRequest( - val name: String, - val civilId: String -) \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/OrderController.kt b/src/main/kotlin/com/coded/spring/ordering/OrderController.kt deleted file mode 100644 index f5ade83..0000000 --- a/src/main/kotlin/com/coded/spring/ordering/OrderController.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.coded.spring.ordering - -import org.springframework.web.bind.annotation.GetMapping -import org.springframework.web.bind.annotation.PostMapping -import org.springframework.web.bind.annotation.RequestBody -import org.springframework.web.bind.annotation.RestController - - -@RestController // Optional: makes your API cleaner -class OrderController(val orderRepository: OrderRepository) { - - @PostMapping("/orders") - fun submitOrder(@RequestBody request: OrderRequest): Order { - val order = Order( - username = request.username, - resturant = request.resturant, - items = request.items - ) - return orderRepository.save(order) - } - - @GetMapping("/listOrders") - fun listOrders(): List { - return orderRepository.findAll() - } -} - -data class OrderRequest( - val username: String, - val resturant: String, - val items: List -) \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/UsersOrder.kt b/src/main/kotlin/com/coded/spring/ordering/UsersOrder.kt deleted file mode 100644 index d26d670..0000000 --- a/src/main/kotlin/com/coded/spring/ordering/UsersOrder.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.coded.spring.ordering - -import jakarta.persistence.* -import org.springframework.data.jpa.repository.JpaRepository -import org.springframework.stereotype.Repository - -@Repository -interface OrderRepository : JpaRepository - -@Entity -@Table(name = "orders") -data class Order( - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - val id: Long? = null, - val username: String, - val resturant: String, - - @ElementCollection - @CollectionTable(name = "order_items", joinColumns = [JoinColumn(name = "order_id")]) - @Column(name = "item") - val items: List -) { - constructor() : this(null, "", "", emptyList()) -} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/UsersRepository.kt b/src/main/kotlin/com/coded/spring/ordering/UsersRepository.kt deleted file mode 100644 index 916bdeb..0000000 --- a/src/main/kotlin/com/coded/spring/ordering/UsersRepository.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.coded.spring.ordering - -import jakarta.inject.Named -import jakarta.persistence.* -import org.springframework.data.jpa.repository.JpaRepository - -@Named -interface UsersRepository : JpaRepository - -@Entity -@Table(name = "users") -data class User( - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - var id: Long? = null, - var name: String -){ - constructor(resturant: String, user: String, items: String) : this(null, "") -} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/controller/ItemController.kt b/src/main/kotlin/com/coded/spring/ordering/controller/ItemController.kt new file mode 100644 index 0000000..abb6045 --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/controller/ItemController.kt @@ -0,0 +1,22 @@ +package com.coded.spring.ordering.controller + +import com.coded.spring.ordering.model.Item +import com.coded.spring.ordering.service.ItemService +import org.springframework.web.bind.annotation.* + +@RestController +class ItemController(private val itemService: ItemService) { + + @PostMapping("/items/{orderId}") + fun createItem( + @PathVariable orderId: Long, + @RequestBody body: Map + ): Item { + val name = body["name"] as? String ?: throw Exception("name is required") + val quantity = (body["quantity"] as? Int) ?: 1 + return itemService.createItem(orderId, name, quantity) + } + + @GetMapping("/items") + fun getAllItems(): List = itemService.getAllItems() +} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/controller/OrderController.kt b/src/main/kotlin/com/coded/spring/ordering/controller/OrderController.kt new file mode 100644 index 0000000..c258e50 --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/controller/OrderController.kt @@ -0,0 +1,20 @@ +package com.coded.spring.ordering.controller + +import com.coded.spring.ordering.model.Order +import com.coded.spring.ordering.service.OrderService +import org.springframework.web.bind.annotation.* + +@RestController +@RequestMapping("/orders") +class OrderController(private val orderService: OrderService) { + + @PostMapping("/{userId}") + fun createOrder(@PathVariable userId: Long): Order { + return orderService.createOrder(userId) + } + + @GetMapping + fun getAllOrders(): List { + return orderService.getAllOrders() + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/controller/UserController.kt b/src/main/kotlin/com/coded/spring/ordering/controller/UserController.kt new file mode 100644 index 0000000..cbfee4d --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/controller/UserController.kt @@ -0,0 +1,20 @@ +package com.coded.spring.ordering.controller + +import com.coded.spring.ordering.model.User +import com.coded.spring.ordering.service.UserService +import org.springframework.web.bind.annotation.* + +@RestController +@RequestMapping("/users") +class UserController(private val userService: UserService) { + + @PostMapping + fun createUser(@RequestBody user: User): User { + return userService.createUser(user) + } + + @GetMapping + fun getAllUsers(): List { + return userService.getAllUsers() + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/model/Item.kt b/src/main/kotlin/com/coded/spring/ordering/model/Item.kt new file mode 100644 index 0000000..c3bfa73 --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/model/Item.kt @@ -0,0 +1,19 @@ +package com.coded.spring.ordering.model + +import jakarta.persistence.* + +@Entity +@Table(name = "items") +data class Item( + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + val id: Long = 0, + + @ManyToOne + val order: Order = Order(), + + val name: String = "", + + val quantity: Int = 1 +) { + constructor() : this(0, Order(), "", 1) +} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/model/Order.kt b/src/main/kotlin/com/coded/spring/ordering/model/Order.kt new file mode 100644 index 0000000..3bb3ebf --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/model/Order.kt @@ -0,0 +1,15 @@ +package com.coded.spring.ordering.model + +import jakarta.persistence.* + +@Entity +@Table(name = "orders") +data class Order( + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + val id: Long = 0, + + @ManyToOne + val user: User = User() +) { + constructor() : this(0, User()) +} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/model/User.kt b/src/main/kotlin/com/coded/spring/ordering/model/User.kt new file mode 100644 index 0000000..d608057 --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/model/User.kt @@ -0,0 +1,14 @@ +package com.coded.spring.ordering.model + +import jakarta.persistence.* + +@Entity +@Table(name = "users") +data class User( + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + val id: Long = 0, + val username: String = "", + val age: Int = 0 +) { + constructor() : this(0, "", 0) +} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/repository/ItemRepository.kt b/src/main/kotlin/com/coded/spring/ordering/repository/ItemRepository.kt new file mode 100644 index 0000000..8265947 --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/repository/ItemRepository.kt @@ -0,0 +1,6 @@ +package com.coded.spring.ordering.repository + +import com.coded.spring.ordering.model.Item +import org.springframework.data.jpa.repository.JpaRepository + +interface ItemRepository : JpaRepository \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/repository/OrderRepository.kt b/src/main/kotlin/com/coded/spring/ordering/repository/OrderRepository.kt new file mode 100644 index 0000000..99f0ecc --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/repository/OrderRepository.kt @@ -0,0 +1,6 @@ +package com.coded.spring.ordering.repository + +import com.coded.spring.ordering.model.Order +import org.springframework.data.jpa.repository.JpaRepository + +interface OrderRepository : JpaRepository \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/repository/UserRepository.kt b/src/main/kotlin/com/coded/spring/ordering/repository/UserRepository.kt new file mode 100644 index 0000000..7dc9bf5 --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/repository/UserRepository.kt @@ -0,0 +1,6 @@ +package com.coded.spring.ordering.repository + +import com.coded.spring.ordering.model.User +import org.springframework.data.jpa.repository.JpaRepository + +interface UserRepository : JpaRepository \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/service/ItemService.kt b/src/main/kotlin/com/coded/spring/ordering/service/ItemService.kt new file mode 100644 index 0000000..aa77176 --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/service/ItemService.kt @@ -0,0 +1,19 @@ +package com.coded.spring.ordering.service + +import com.coded.spring.ordering.model.Item +import com.coded.spring.ordering.repository.ItemRepository +import com.coded.spring.ordering.repository.OrderRepository +import org.springframework.stereotype.Service + +@Service +class ItemService( + private val itemRepository: ItemRepository, + private val orderRepository: OrderRepository +) { + fun createItem(orderId: Long, name: String, quantity: Int): Item { + val order = orderRepository.findById(orderId).orElseThrow { Exception("Order not found") } + return itemRepository.save(Item(order = order, name = name, quantity = quantity)) + } + + fun getAllItems(): List = itemRepository.findAll() +} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/service/OrderService.kt b/src/main/kotlin/com/coded/spring/ordering/service/OrderService.kt new file mode 100644 index 0000000..a8214c4 --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/service/OrderService.kt @@ -0,0 +1,19 @@ +package com.coded.spring.ordering.service + +import com.coded.spring.ordering.model.Order +import com.coded.spring.ordering.repository.OrderRepository +import com.coded.spring.ordering.repository.UserRepository +import org.springframework.stereotype.Service + +@Service +class OrderService( + private val orderRepository: OrderRepository, + private val userRepository: UserRepository +) { + fun createOrder(userId: Long): Order { + val user = userRepository.findById(userId).orElseThrow { Exception("User not found") } + return orderRepository.save(Order(user = user)) + } + + fun getAllOrders(): List = orderRepository.findAll() +} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/service/UserService.kt b/src/main/kotlin/com/coded/spring/ordering/service/UserService.kt new file mode 100644 index 0000000..b4fcb01 --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/service/UserService.kt @@ -0,0 +1,11 @@ +package com.coded.spring.ordering.service + +import com.coded.spring.ordering.model.User +import com.coded.spring.ordering.repository.UserRepository +import org.springframework.stereotype.Service + +@Service +class UserService(private val userRepository: UserRepository) { + fun createUser(user: User): User = userRepository.save(user) + fun getAllUsers(): List = userRepository.findAll() +} \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 3704dc6..3ec1f6b 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1,7 @@ spring.application.name=Kotlin.SpringbootV2 +server-welcome-message= Hello World by Hussain +spring.datasource.url=jdbc:postgresql://localhost:8080/orders +spring.datasource.username=postgres +spring.datasource.password=12345678 +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect +server.port=8081 \ No newline at end of file From 4fd500c24f9695b29cb1d90f20c07ece35aa2818 Mon Sep 17 00:00:00 2001 From: hussainjg Date: Fri, 11 Apr 2025 11:21:19 +0300 Subject: [PATCH 3/7] I re organized the files again --- .../ordering/controller/ItemController.kt | 2 +- .../ordering/controller/OrderController.kt | 2 +- .../ordering/controller/UserController.kt | 2 +- .../com/coded/spring/ordering/model/Item.kt | 19 -------------- .../com/coded/spring/ordering/model/Order.kt | 15 ----------- .../com/coded/spring/ordering/model/User.kt | 14 ---------- .../ordering/repository/ItemRepository.kt | 26 +++++++++++++++++-- .../ordering/repository/OrderRepository.kt | 22 ++++++++++++++-- .../ordering/repository/UserRepository.kt | 20 ++++++++++++-- .../spring/ordering/service/ItemService.kt | 2 +- .../spring/ordering/service/OrderService.kt | 2 +- .../spring/ordering/service/UserService.kt | 2 +- 12 files changed, 68 insertions(+), 60 deletions(-) delete mode 100644 src/main/kotlin/com/coded/spring/ordering/model/Item.kt delete mode 100644 src/main/kotlin/com/coded/spring/ordering/model/Order.kt delete mode 100644 src/main/kotlin/com/coded/spring/ordering/model/User.kt diff --git a/src/main/kotlin/com/coded/spring/ordering/controller/ItemController.kt b/src/main/kotlin/com/coded/spring/ordering/controller/ItemController.kt index abb6045..0fa76b9 100644 --- a/src/main/kotlin/com/coded/spring/ordering/controller/ItemController.kt +++ b/src/main/kotlin/com/coded/spring/ordering/controller/ItemController.kt @@ -1,6 +1,6 @@ package com.coded.spring.ordering.controller -import com.coded.spring.ordering.model.Item +import com.coded.spring.ordering.repository.Item import com.coded.spring.ordering.service.ItemService import org.springframework.web.bind.annotation.* diff --git a/src/main/kotlin/com/coded/spring/ordering/controller/OrderController.kt b/src/main/kotlin/com/coded/spring/ordering/controller/OrderController.kt index c258e50..45097be 100644 --- a/src/main/kotlin/com/coded/spring/ordering/controller/OrderController.kt +++ b/src/main/kotlin/com/coded/spring/ordering/controller/OrderController.kt @@ -1,6 +1,6 @@ package com.coded.spring.ordering.controller -import com.coded.spring.ordering.model.Order +import com.coded.spring.ordering.repository.Order import com.coded.spring.ordering.service.OrderService import org.springframework.web.bind.annotation.* diff --git a/src/main/kotlin/com/coded/spring/ordering/controller/UserController.kt b/src/main/kotlin/com/coded/spring/ordering/controller/UserController.kt index cbfee4d..bfc5a6b 100644 --- a/src/main/kotlin/com/coded/spring/ordering/controller/UserController.kt +++ b/src/main/kotlin/com/coded/spring/ordering/controller/UserController.kt @@ -1,6 +1,6 @@ package com.coded.spring.ordering.controller -import com.coded.spring.ordering.model.User +import com.coded.spring.ordering.repository.User import com.coded.spring.ordering.service.UserService import org.springframework.web.bind.annotation.* diff --git a/src/main/kotlin/com/coded/spring/ordering/model/Item.kt b/src/main/kotlin/com/coded/spring/ordering/model/Item.kt deleted file mode 100644 index c3bfa73..0000000 --- a/src/main/kotlin/com/coded/spring/ordering/model/Item.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.coded.spring.ordering.model - -import jakarta.persistence.* - -@Entity -@Table(name = "items") -data class Item( - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - val id: Long = 0, - - @ManyToOne - val order: Order = Order(), - - val name: String = "", - - val quantity: Int = 1 -) { - constructor() : this(0, Order(), "", 1) -} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/model/Order.kt b/src/main/kotlin/com/coded/spring/ordering/model/Order.kt deleted file mode 100644 index 3bb3ebf..0000000 --- a/src/main/kotlin/com/coded/spring/ordering/model/Order.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.coded.spring.ordering.model - -import jakarta.persistence.* - -@Entity -@Table(name = "orders") -data class Order( - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - val id: Long = 0, - - @ManyToOne - val user: User = User() -) { - constructor() : this(0, User()) -} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/model/User.kt b/src/main/kotlin/com/coded/spring/ordering/model/User.kt deleted file mode 100644 index d608057..0000000 --- a/src/main/kotlin/com/coded/spring/ordering/model/User.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.coded.spring.ordering.model - -import jakarta.persistence.* - -@Entity -@Table(name = "users") -data class User( - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - val id: Long = 0, - val username: String = "", - val age: Int = 0 -) { - constructor() : this(0, "", 0) -} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/repository/ItemRepository.kt b/src/main/kotlin/com/coded/spring/ordering/repository/ItemRepository.kt index 8265947..13f7982 100644 --- a/src/main/kotlin/com/coded/spring/ordering/repository/ItemRepository.kt +++ b/src/main/kotlin/com/coded/spring/ordering/repository/ItemRepository.kt @@ -1,6 +1,28 @@ package com.coded.spring.ordering.repository -import com.coded.spring.ordering.model.Item + +import jakarta.persistence.Entity +import jakarta.persistence.GeneratedValue +import jakarta.persistence.GenerationType +import jakarta.persistence.Id +import jakarta.persistence.ManyToOne +import jakarta.persistence.Table import org.springframework.data.jpa.repository.JpaRepository -interface ItemRepository : JpaRepository \ No newline at end of file +interface ItemRepository : JpaRepository + +@Entity +@Table(name = "items") +data class Item( + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + val id: Long = 0, + + @ManyToOne + val order: com.coded.spring.ordering.repository.Order = Order(), + + val name: String = "", + + val quantity: Int = 1 +) { + constructor() : this(0, Order(), "", 1) +} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/repository/OrderRepository.kt b/src/main/kotlin/com/coded/spring/ordering/repository/OrderRepository.kt index 99f0ecc..3d49e8c 100644 --- a/src/main/kotlin/com/coded/spring/ordering/repository/OrderRepository.kt +++ b/src/main/kotlin/com/coded/spring/ordering/repository/OrderRepository.kt @@ -1,6 +1,24 @@ package com.coded.spring.ordering.repository -import com.coded.spring.ordering.model.Order + +import jakarta.persistence.Entity +import jakarta.persistence.GeneratedValue +import jakarta.persistence.GenerationType +import jakarta.persistence.Id +import jakarta.persistence.ManyToOne +import jakarta.persistence.Table import org.springframework.data.jpa.repository.JpaRepository -interface OrderRepository : JpaRepository \ No newline at end of file +interface OrderRepository : JpaRepository + +@Entity +@Table(name = "orders") +data class Order( + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + val id: Long = 0, + + @ManyToOne + val user: com.coded.spring.ordering.repository.User = User() +) { + constructor() : this(0, User()) +} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/repository/UserRepository.kt b/src/main/kotlin/com/coded/spring/ordering/repository/UserRepository.kt index 7dc9bf5..5e26113 100644 --- a/src/main/kotlin/com/coded/spring/ordering/repository/UserRepository.kt +++ b/src/main/kotlin/com/coded/spring/ordering/repository/UserRepository.kt @@ -1,6 +1,22 @@ package com.coded.spring.ordering.repository -import com.coded.spring.ordering.model.User + +import jakarta.persistence.Entity +import jakarta.persistence.GeneratedValue +import jakarta.persistence.GenerationType +import jakarta.persistence.Id +import jakarta.persistence.Table import org.springframework.data.jpa.repository.JpaRepository -interface UserRepository : JpaRepository \ No newline at end of file +interface UserRepository : JpaRepository + +@Entity +@Table(name = "users") +data class User( + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + val id: Long = 0, + val username: String = "", + val age: Int = 0 +) { + constructor() : this(0, "", 0) +} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/service/ItemService.kt b/src/main/kotlin/com/coded/spring/ordering/service/ItemService.kt index aa77176..13a4494 100644 --- a/src/main/kotlin/com/coded/spring/ordering/service/ItemService.kt +++ b/src/main/kotlin/com/coded/spring/ordering/service/ItemService.kt @@ -1,6 +1,6 @@ package com.coded.spring.ordering.service -import com.coded.spring.ordering.model.Item +import com.coded.spring.ordering.repository.Item import com.coded.spring.ordering.repository.ItemRepository import com.coded.spring.ordering.repository.OrderRepository import org.springframework.stereotype.Service diff --git a/src/main/kotlin/com/coded/spring/ordering/service/OrderService.kt b/src/main/kotlin/com/coded/spring/ordering/service/OrderService.kt index a8214c4..a679c78 100644 --- a/src/main/kotlin/com/coded/spring/ordering/service/OrderService.kt +++ b/src/main/kotlin/com/coded/spring/ordering/service/OrderService.kt @@ -1,6 +1,6 @@ package com.coded.spring.ordering.service -import com.coded.spring.ordering.model.Order +import com.coded.spring.ordering.repository.Order import com.coded.spring.ordering.repository.OrderRepository import com.coded.spring.ordering.repository.UserRepository import org.springframework.stereotype.Service diff --git a/src/main/kotlin/com/coded/spring/ordering/service/UserService.kt b/src/main/kotlin/com/coded/spring/ordering/service/UserService.kt index b4fcb01..b2afda8 100644 --- a/src/main/kotlin/com/coded/spring/ordering/service/UserService.kt +++ b/src/main/kotlin/com/coded/spring/ordering/service/UserService.kt @@ -1,6 +1,6 @@ package com.coded.spring.ordering.service -import com.coded.spring.ordering.model.User +import com.coded.spring.ordering.repository.User import com.coded.spring.ordering.repository.UserRepository import org.springframework.stereotype.Service From ab87f75b9e0a3531667e16e9cdb4c27306805673 Mon Sep 17 00:00:00 2001 From: hussainjg Date: Sun, 20 Apr 2025 20:16:52 +0300 Subject: [PATCH 4/7] Updated --- .DS_Store | Bin 6148 -> 6148 bytes pom.xml | 21 ++++++ src/.DS_Store | Bin 6148 -> 6148 bytes src/main/.DS_Store | Bin 6148 -> 6148 bytes src/main/kotlin/.DS_Store | Bin 6148 -> 6148 bytes src/main/kotlin/com/.DS_Store | Bin 6148 -> 6148 bytes src/main/kotlin/com/coded/.DS_Store | Bin 6148 -> 6148 bytes src/main/kotlin/com/coded/spring/.DS_Store | Bin 6148 -> 6148 bytes .../com/coded/spring/ordering/.DS_Store | Bin 0 -> 6148 bytes .../coded/spring/ordering/InitUserRunner.kt | 34 ++++++++++ .../CustomUserDetailsService.kt | 19 ++++++ .../ordering/authentication/SecurityConfig.kt | 63 ++++++++++++++++++ .../jwt/AuthenticationController.kt | 39 +++++++++++ .../jwt/JwtAuthenticationFilter.kt | 45 +++++++++++++ .../ordering/authentication/jwt/JwtService.kt | 42 ++++++++++++ .../ordering/controller/ItemController.kt | 2 +- .../ordering/controller/MenuController.kt | 20 ++++++ .../ordering/controller/OrderController.kt | 2 +- .../ordering/controller/ProfilesController.kt | 33 +++++++++ .../ordering/controller/UserController.kt | 26 ++++++-- .../com/coded/spring/ordering/model/Item.kt | 24 +++++++ .../coded/spring/ordering/model/MenuItem.kt | 17 +++++ .../com/coded/spring/ordering/model/Order.kt | 21 ++++++ .../coded/spring/ordering/model/Profiles.kt | 22 ++++++ .../com/coded/spring/ordering/model/User.kt | 32 +++++++++ .../ordering/repository/ItemRepository.kt | 22 +----- .../ordering/repository/MenuItemRepository.kt | 6 ++ .../ordering/repository/OrderRepository.kt | 19 +----- .../ordering/repository/ProfileRepository.kt | 8 +++ .../ordering/repository/UserRepository.kt | 22 ++---- .../spring/ordering/service/ItemService.kt | 2 +- .../spring/ordering/service/MenuService.kt | 14 ++++ .../spring/ordering/service/OrderService.kt | 2 +- .../ordering/service/ProfilesService.kt | 46 +++++++++++++ .../spring/ordering/service/UserService.kt | 4 +- src/main/resources/application.properties | 1 + 36 files changed, 540 insertions(+), 68 deletions(-) create mode 100644 src/main/kotlin/com/coded/spring/ordering/.DS_Store create mode 100644 src/main/kotlin/com/coded/spring/ordering/InitUserRunner.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/authentication/CustomUserDetailsService.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/authentication/SecurityConfig.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/authentication/jwt/AuthenticationController.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/authentication/jwt/JwtAuthenticationFilter.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/authentication/jwt/JwtService.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/controller/MenuController.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/controller/ProfilesController.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/model/Item.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/model/MenuItem.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/model/Order.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/model/Profiles.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/model/User.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/repository/MenuItemRepository.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/repository/ProfileRepository.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/service/MenuService.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/service/ProfilesService.kt diff --git a/.DS_Store b/.DS_Store index dff2667ee4f6c9c06c77b6cdecd76332e5f2b16e..bff4f9e7e7036fe82ce14578459537e287057783 100644 GIT binary patch delta 327 zcmZoMXfc=|#>B)qu~2NHo+2aH#DLw4m>3zkCi5`fsLx3^3{K9^EnonH75zYpnW31W zh#@&Q-^C>B`mu~2NHo+2aD#DLwC4MbQb^D|xLDGM&j%gN76XJBAp-29PQjAauG iBhzMf4t@@x2B5%q=E?jbmK;E721W)3rp*B&TbKceMHDgs diff --git a/pom.xml b/pom.xml index 8186cd9..49c0d96 100644 --- a/pom.xml +++ b/pom.xml @@ -74,6 +74,27 @@ org.postgresql postgresql + + org.springframework.boot + spring-boot-starter-security + + + io.jsonwebtoken + jjwt-api + 0.11.5 + + + io.jsonwebtoken + jjwt-impl + runtime + 0.11.5 + + + io.jsonwebtoken + jjwt-jackson + runtime + 0.11.5 + diff --git a/src/.DS_Store b/src/.DS_Store index 78928e5ea5732513dcc37ad4c9fbb6864610b875..e9086dd2450e1e125231a2d219da0d13c121f451 100644 GIT binary patch delta 326 zcmZoMXfc=|#>B)qu~2NHo+2aH#DLw41(+BaxhC^4-l@+?Hw;eB&n;j8gZ@20iiIJU zA(0`IAul)I#U&{xKM5$tF>i0=)x(#LIikv^;FT}PKr)*#0AvH)?6TmZyqx^J$?q9C z>RA{{7*ZLE8A?zc!*Cv~0V;>=82+M_8Jl5_fy*NtgH0aAF$@AA$3Vem9wtea&Fmcf e9KcZ8%*gbec{0CB`mu~2NHo+2aD#DLwC4MbQb^E2J#DGM&j%gN76XJBAp-29PQjAawc jU&hVs9Q+(W4M2hK%#-;=EIEME42%p6Oq&BlwlD(#sd*JK diff --git a/src/main/.DS_Store b/src/main/.DS_Store index a627e920e51cb7f16362ac2992e4293f6836df3e..47dc945d310e4618091447c847e7d91cc1a929cd 100644 GIT binary patch delta 364 zcmZoMXfc=|#>B!ku~2NHo+2aH#DLw41(=u_xhC^4KB>=1Hw;eB&n;j8gR*iU#m11$ zkk3%Uki(G4ke8e9;*yk;p9B==VCjpzdic^YM@%&-1l1H|AlbvH05k$@&*bNf67`%6 zMGUD7#Xw6-fvjW@8`W8iASVU(3bl%V5W0Rf%vSx=LA8t5ICaAh4N{=?UXz ib`E|HU>E{9-B`mu~2NHo+2aD#DLwC4MbQb^RqmhT*1n}S%gEFWn;rv#?9;;{2V}a dn*}+(Gf(Chu@qnc0!9V~CMeCaIYML&GXP1f5xxKb diff --git a/src/main/kotlin/.DS_Store b/src/main/kotlin/.DS_Store index 53a9e076fa9d47cbd1b4c9e3b1740a2940ac92c7..cd008e9d166984efb50f8c8a0141358e897655c7 100644 GIT binary patch delta 168 zcmZoMXfc=|#>B)qu~2NHo+2aL#DLw4m>3z^Ci5`fNXtn#3{K9^EnonHxMCp1%#h5G z&ybs&@8Xh_lb-|>;gEN_Cz*Tsm?N@m3Le>l3?x$-85lO-V%*EJnVo~51L%&;9~r+h TPv#e~B`mu~2NHo+2aD#DLwC4MbQb^D|xD9KyVrWn)7D<7Rdaeh#3T&56w4 WnJ4p$SaL7`0V4wg)8+t?EzAIm=Mg0U diff --git a/src/main/kotlin/com/.DS_Store b/src/main/kotlin/com/.DS_Store index 33a724c9ba637d3da4a8bd8a33298d96a7c7a4cc..b3d2d66aee3c78f5fdcd66cc1545c926fa9d6583 100644 GIT binary patch delta 194 zcmZoMXfc=|#>B)qu~2NHo+2aL#DLw41(+Ba*(UQaKB&)0Hw;eB&n;j81Gju2#mbP( zkk639kjjvfoA2V1l#`zX6y*?Bj=XyK(lJML6)6N%6l5UV@BpYC$%f6Z8RxKUX6NAN d0J?B9Bhz>0$^0Ug9E=PMK*YeXIY49!GXPB(EtdcQ delta 68 zcmZoMXfc=|#>B`mu~2NHo+2aD#DLwC4MbQb^E2JuoWneuWn)7F<7Rdaeh#3T&5g|8 WnJ4p$SaL7`0V4wg)8+t?EzAItFA-e; diff --git a/src/main/kotlin/com/coded/.DS_Store b/src/main/kotlin/com/coded/.DS_Store index 0e597ff43d1419505a291c641d213b1929ed3fb8..ccf8a4612f6ae848d527e905b9ca099f06859a39 100644 GIT binary patch delta 194 zcmZoMXfc=|#>B)qu~2NHo+2aL#DLw41(+Ba*(UQaKB>=1Hw;eB&n;j81HEh@#l}#~ zP{2^ckjaq8ke-|G;*yk;p9B==xcunT^~0BrIby0wA*iMx1KFMfKqJ8RY<|u-gJm;2 f2R{eUg_{|fzB5ne7qR4EWMBXy28PW6B3qaN33M_e delta 68 zcmZoMXfc=|#>B`mu~2NHo+2aD#DLwC4MbQb^D{l%T*2JWvaz9qaWgvyKL=3F=84ST WnJ4p$SaL7`0V4wg)8+t?EzAIwQxSOp diff --git a/src/main/kotlin/com/coded/spring/.DS_Store b/src/main/kotlin/com/coded/spring/.DS_Store index 47ed89994bccfa2957b710ed27f4cadfea1dd7b7..4b248e646192de301e4bf4eeca433debc7b39e91 100644 GIT binary patch delta 200 zcmZoMXfc=|#>B)qu~2NHo+2aL#DLw46_^+q*(UQazNybiHw;eB&n;j81F>`<#leuz zP{feJkP0L-8S)s?bMswXl5+BsKyp{S7Ts>Xa?BCCx)h?+6=cBeWCfbDfMN3!#%`9) h>>T_YKzD8yWctoLnP0?`gOPy&h!_|)2Z(H81^_WqF{A(h delta 73 zcmZoMXfc=|#>B`mu~2NHo+2aD#DLwC4MbQb8#4<|R$#iZc>;4e%jONtGZ;6sbMSKj c6>eV0{GE9+zlbFV0}wDWFfeTn5ZS^E0PrLdumAu6 diff --git a/src/main/kotlin/com/coded/spring/ordering/.DS_Store b/src/main/kotlin/com/coded/spring/ordering/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..ccb6d3c6de4117983ffa3b959f9707cbdd76aaa3 GIT binary patch literal 6148 zcmeHKOHRWu5FM97Lt)V+%Wwm_U>~Y*f*ydXX#_|Kj><{XSa6gw;41CKW(6}+yWGTZZrFDy~ z4S&%AUb`_RShpLx!>U#5mt9WhiOmZUJ>oAwCoi{gyv*zp{lUxA;`sUP^{k(}`Z2e- zs?UGIGRDxCQUQ&(bPcr@_m5jTZ6B|$Gd`{9>=-k*8=c>AJ9LhqkADFVP?=ELRJivJ zg16!j!}ytvKcN^m zJH`(kolGRCwK|{mL@1)+ZgoDEv31HbCPCz76c_y7O^ literal 0 HcmV?d00001 diff --git a/src/main/kotlin/com/coded/spring/ordering/InitUserRunner.kt b/src/main/kotlin/com/coded/spring/ordering/InitUserRunner.kt new file mode 100644 index 0000000..1f87083 --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/InitUserRunner.kt @@ -0,0 +1,34 @@ +package com.coded.spring.ordering + +import com.coded.spring.ordering.model.Roles +import com.coded.spring.ordering.model.User +import com.coded.spring.ordering.repository.* +import org.springframework.boot.CommandLineRunner +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication +import org.springframework.context.annotation.Bean +import org.springframework.security.crypto.password.PasswordEncoder + +@SpringBootApplication +class InitUserRunner { + @Bean + fun initUsers(userRepository: UserRepository, passwordEncoder: PasswordEncoder) = CommandLineRunner { + val user = User( + name = "HelloUser", + username = "testuser", + password = passwordEncoder.encode("password123"), + age = 18, + role = Roles.USER + ) + if (userRepository.findByUsername(user.username) == null) { + println("Creating user ${user.username}") + userRepository.save(user) + } else { + println("User ${user.username} already exists") + } + } +} + +fun main(args: Array) { + runApplication(*args).close() +} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/authentication/CustomUserDetailsService.kt b/src/main/kotlin/com/coded/spring/ordering/authentication/CustomUserDetailsService.kt new file mode 100644 index 0000000..5501450 --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/authentication/CustomUserDetailsService.kt @@ -0,0 +1,19 @@ +package com.coded.spring.ordering.authentication + +import org.springframework.security.core.userdetails.* +import com.coded.spring.ordering.repository.UserRepository +import org.springframework.stereotype.Service + +@Service +class CustomUserDetailsService( + private val usersRepository: UserRepository) : UserDetailsService { + override fun loadUserByUsername(username: String): UserDetails { + val user = usersRepository.findByUsername(username) ?: throw UsernameNotFoundException("User not found") + + return User.builder() + .username(user.username) + .password(user.password) + .roles(user.role.toString()) + .build() + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/authentication/SecurityConfig.kt b/src/main/kotlin/com/coded/spring/ordering/authentication/SecurityConfig.kt new file mode 100644 index 0000000..4a199fd --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/authentication/SecurityConfig.kt @@ -0,0 +1,63 @@ +package com.coded.spring.ordering.authentication + +import com.coded.spring.ordering.authentication.jwt.JwtAuthenticationFilter +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.security.authentication.AuthenticationManager +import org.springframework.security.authentication.AuthenticationProvider +import org.springframework.security.authentication.dao.DaoAuthenticationProvider +import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration +import org.springframework.security.config.annotation.web.builders.HttpSecurity +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity +import org.springframework.security.config.http.SessionCreationPolicy +import org.springframework.security.core.userdetails.UserDetailsService +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder +import org.springframework.security.crypto.password.PasswordEncoder +import org.springframework.security.web.SecurityFilterChain +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter + + +@Configuration +@EnableWebSecurity +class SecurityConfig( + private val jwtAuthFilter: JwtAuthenticationFilter, + private val userDetailsService: UserDetailsService +) { + + @Bean + fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { + http.csrf { it.disable() } + .authorizeHttpRequests { + it + .requestMatchers("/auth/**").permitAll() + .requestMatchers("/users/create").permitAll() + .requestMatchers("/users/**").hasRole("ADMIN") + .requestMatchers("/profile/**").authenticated() + .requestMatchers("/menu/**").authenticated() + + .anyRequest().authenticated() + } + .sessionManagement { + it.sessionCreationPolicy(SessionCreationPolicy.STATELESS) + } + .authenticationProvider(authenticationProvider()) + .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter::class.java) + + return http.build() + } + + @Bean + fun passwordEncoder(): PasswordEncoder = BCryptPasswordEncoder() + + @Bean + fun authenticationManager(config: AuthenticationConfiguration): AuthenticationManager = + config.authenticationManager + + @Bean + fun authenticationProvider(): AuthenticationProvider { + val provider = DaoAuthenticationProvider() + provider.setUserDetailsService(userDetailsService) + provider.setPasswordEncoder(passwordEncoder()) + return provider + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/authentication/jwt/AuthenticationController.kt b/src/main/kotlin/com/coded/spring/ordering/authentication/jwt/AuthenticationController.kt new file mode 100644 index 0000000..e579c57 --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/authentication/jwt/AuthenticationController.kt @@ -0,0 +1,39 @@ +package com.coded.spring.ordering.authentication.jwt + +import org.springframework.security.authentication.* +import org.springframework.security.core.userdetails.UserDetailsService +import org.springframework.security.core.userdetails.UsernameNotFoundException +import org.springframework.web.bind.annotation.* + + +@RestController +@RequestMapping("/auth") +class AuthenticationController( + private val authenticationManager: AuthenticationManager, + private val userDetailsService: UserDetailsService, + private val jwtService: JwtService +) { + + @PostMapping("/login") + fun login(@RequestBody authRequest: AuthenticationRequest): AuthenticationResponse { + val authToken = UsernamePasswordAuthenticationToken(authRequest.username, authRequest.password) + val authentication = authenticationManager.authenticate(authToken) + + if (authentication.isAuthenticated) { + val userDetails = userDetailsService.loadUserByUsername(authRequest.username) + val token = jwtService.generateToken(userDetails.username) + return AuthenticationResponse (token) + } else { + throw UsernameNotFoundException("Invalid user request!") + } + } +} + +data class AuthenticationRequest( + val username: String, + val password: String +) + +data class AuthenticationResponse( + val token: String +) \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/authentication/jwt/JwtAuthenticationFilter.kt b/src/main/kotlin/com/coded/spring/ordering/authentication/jwt/JwtAuthenticationFilter.kt new file mode 100644 index 0000000..f180b7c --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/authentication/jwt/JwtAuthenticationFilter.kt @@ -0,0 +1,45 @@ +package com.coded.spring.ordering.authentication.jwt + +import jakarta.servlet.FilterChain +import jakarta.servlet.http.* +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken +import org.springframework.security.core.context.SecurityContextHolder +import org.springframework.security.core.userdetails.UserDetailsService +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource +import org.springframework.stereotype.Component +import org.springframework.web.filter.OncePerRequestFilter + +@Component +class JwtAuthenticationFilter( + private val jwtService: JwtService, + private val userDetailsService: UserDetailsService +) : OncePerRequestFilter() { + + override fun doFilterInternal( + request: HttpServletRequest, + response: HttpServletResponse, + filterChain: FilterChain + ) { + val authHeader = request.getHeader("Authorization") + if (authHeader == null || !authHeader.startsWith("Bearer ")) { + filterChain.doFilter(request, response) + return + } + + val token = authHeader.substring(7) + val username = jwtService.extractUsername(token) + + if (SecurityContextHolder.getContext().authentication == null) { + if (jwtService.isTokenValid(token, username)) { + val userDetails = userDetailsService.loadUserByUsername(username) + val authToken = UsernamePasswordAuthenticationToken( + userDetails, null, userDetails.authorities + ) + authToken.details = WebAuthenticationDetailsSource().buildDetails(request) + SecurityContextHolder.getContext().authentication = authToken + } + } + + filterChain.doFilter(request, response) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/authentication/jwt/JwtService.kt b/src/main/kotlin/com/coded/spring/ordering/authentication/jwt/JwtService.kt new file mode 100644 index 0000000..c877c7c --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/authentication/jwt/JwtService.kt @@ -0,0 +1,42 @@ +package com.coded.spring.ordering.authentication.jwt + +import io.jsonwebtoken.* +import io.jsonwebtoken.security.Keys +import org.springframework.stereotype.Component +import java.util.* +import javax.crypto.SecretKey + +@Component +class JwtService { + + private val secretKey: SecretKey = Keys.secretKeyFor(SignatureAlgorithm.HS256) + private val expirationMs: Long = 1000 * 60 * 60 + + fun generateToken(username: String): String { + val now = Date() + val expiry = Date(now.time + expirationMs) + + return Jwts.builder() + .setSubject(username) + .setIssuedAt(now) + .setExpiration(expiry) + .signWith(secretKey) + .compact() + } + + fun extractUsername(token: String): String = + Jwts.parserBuilder() + .setSigningKey(secretKey) + .build() + .parseClaimsJws(token) + .body + .subject + + fun isTokenValid(token: String, username: String): Boolean { + return try { + extractUsername(token) == username + } catch (e: Exception) { + false + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/controller/ItemController.kt b/src/main/kotlin/com/coded/spring/ordering/controller/ItemController.kt index 0fa76b9..abb6045 100644 --- a/src/main/kotlin/com/coded/spring/ordering/controller/ItemController.kt +++ b/src/main/kotlin/com/coded/spring/ordering/controller/ItemController.kt @@ -1,6 +1,6 @@ package com.coded.spring.ordering.controller -import com.coded.spring.ordering.repository.Item +import com.coded.spring.ordering.model.Item import com.coded.spring.ordering.service.ItemService import org.springframework.web.bind.annotation.* diff --git a/src/main/kotlin/com/coded/spring/ordering/controller/MenuController.kt b/src/main/kotlin/com/coded/spring/ordering/controller/MenuController.kt new file mode 100644 index 0000000..e9eca2d --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/controller/MenuController.kt @@ -0,0 +1,20 @@ +package com.coded.spring.ordering.controller + +import com.coded.spring.ordering.model.MenuItem +import com.coded.spring.ordering.service.MenuService +import org.springframework.web.bind.annotation.* + +@RestController +@RequestMapping("/menu") +class MenuController( + private val menuService: MenuService +) { + + @GetMapping + fun getMenu(): List = menuService.getAllMenuItems() + + @PostMapping + fun addMenuItem(@RequestBody menuItem: MenuItem): MenuItem { + return menuService.addMenuItem(menuItem) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/controller/OrderController.kt b/src/main/kotlin/com/coded/spring/ordering/controller/OrderController.kt index 45097be..c258e50 100644 --- a/src/main/kotlin/com/coded/spring/ordering/controller/OrderController.kt +++ b/src/main/kotlin/com/coded/spring/ordering/controller/OrderController.kt @@ -1,6 +1,6 @@ package com.coded.spring.ordering.controller -import com.coded.spring.ordering.repository.Order +import com.coded.spring.ordering.model.Order import com.coded.spring.ordering.service.OrderService import org.springframework.web.bind.annotation.* diff --git a/src/main/kotlin/com/coded/spring/ordering/controller/ProfilesController.kt b/src/main/kotlin/com/coded/spring/ordering/controller/ProfilesController.kt new file mode 100644 index 0000000..31730c5 --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/controller/ProfilesController.kt @@ -0,0 +1,33 @@ +package com.coded.spring.ordering.controllers + +import com.coded.spring.ordering.model.Profile +import com.coded.spring.ordering.service.ProfileService +import org.springframework.web.bind.annotation.* + +@RestController +@RequestMapping("/profile") +class ProfileController( + private val profileService: ProfileService +) { + + @PostMapping + fun createOrUpdateProfile(@RequestBody request: ProfileRequest): Profile { + return profileService.createOrUpdateProfile( + userId = request.userId, + firstName = request.firstName, + lastName = request.lastName, + phoneNumber = request.phoneNumber + ) + } + + @GetMapping("/{userId}") + fun getProfile(@PathVariable userId: Long): Profile? = + profileService.getProfile(userId) +} + +data class ProfileRequest( + val userId: Long, + val firstName: String, + val lastName: String, + val phoneNumber: String +) \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/controller/UserController.kt b/src/main/kotlin/com/coded/spring/ordering/controller/UserController.kt index bfc5a6b..3359a43 100644 --- a/src/main/kotlin/com/coded/spring/ordering/controller/UserController.kt +++ b/src/main/kotlin/com/coded/spring/ordering/controller/UserController.kt @@ -1,19 +1,33 @@ package com.coded.spring.ordering.controller -import com.coded.spring.ordering.repository.User +import com.coded.spring.ordering.model.User +import com.coded.spring.ordering.repository.UserRepository import com.coded.spring.ordering.service.UserService +import org.springframework.http.HttpStatus +import org.springframework.security.crypto.password.PasswordEncoder import org.springframework.web.bind.annotation.* +import org.springframework.web.server.ResponseStatusException @RestController @RequestMapping("/users") -class UserController(private val userService: UserService) { +class UserController(private val userService: UserService, + private val userRepository: UserRepository, + private val passwordEncoder: PasswordEncoder +) { - @PostMapping + + @PostMapping("/create") fun createUser(@RequestBody user: User): User { - return userService.createUser(user) - } + val hashedPassword = passwordEncoder.encode(user.password) + val newUser = user.copy(password = hashedPassword) - @GetMapping + if (userRepository.findByUsername(user.username) != null) { + throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Username already exists") as Throwable + } + + return userRepository.save(newUser) + } + @PostMapping("/getAll") fun getAllUsers(): List { return userService.getAllUsers() } diff --git a/src/main/kotlin/com/coded/spring/ordering/model/Item.kt b/src/main/kotlin/com/coded/spring/ordering/model/Item.kt new file mode 100644 index 0000000..835cc3b --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/model/Item.kt @@ -0,0 +1,24 @@ +package com.coded.spring.ordering.model + +import jakarta.persistence.Entity +import jakarta.persistence.GeneratedValue +import jakarta.persistence.GenerationType +import jakarta.persistence.Id +import jakarta.persistence.ManyToOne +import jakarta.persistence.Table + +@Entity +@Table(name = "items") +data class Item( + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + val id: Long = 0, + + @ManyToOne + val order: Order = Order(), + + val name: String = "", + + val quantity: Int = 1 +) { + constructor() : this(0, Order(), "", 1) +} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/model/MenuItem.kt b/src/main/kotlin/com/coded/spring/ordering/model/MenuItem.kt new file mode 100644 index 0000000..f5d626e --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/model/MenuItem.kt @@ -0,0 +1,17 @@ +package com.coded.spring.ordering.model + +import jakarta.persistence.* + +@Entity +@Table(name = "menu_items") +data class MenuItem( + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + val id: Long = 0, + + val name: String = "", + + val description: String = "", + + val price: Double = 0.0 +) \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/model/Order.kt b/src/main/kotlin/com/coded/spring/ordering/model/Order.kt new file mode 100644 index 0000000..162b11c --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/model/Order.kt @@ -0,0 +1,21 @@ +package com.coded.spring.ordering.model + +import com.coded.spring.ordering.model.User +import jakarta.persistence.Entity +import jakarta.persistence.GeneratedValue +import jakarta.persistence.GenerationType +import jakarta.persistence.Id +import jakarta.persistence.ManyToOne +import jakarta.persistence.Table + +@Entity +@Table(name = "orders") +data class Order( + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + val id: Long = 0, + + @ManyToOne + val user: User = User() +) { + constructor() : this(0, User()) +} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/model/Profiles.kt b/src/main/kotlin/com/coded/spring/ordering/model/Profiles.kt new file mode 100644 index 0000000..2eefbf4 --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/model/Profiles.kt @@ -0,0 +1,22 @@ +package com.coded.spring.ordering.model + + +import jakarta.persistence.* + +@Entity +@Table(name = "profiles") +data class Profile( + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + val id: Long = 0, + + @OneToOne + @JoinColumn(name = "user_id", referencedColumnName = "id", nullable = false, unique = true) + val user: User = User(), + val firstName : String = "", + val lastName : String = "", + val phoneNumber : String = "" + +) + + diff --git a/src/main/kotlin/com/coded/spring/ordering/model/User.kt b/src/main/kotlin/com/coded/spring/ordering/model/User.kt new file mode 100644 index 0000000..bebe4cb --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/model/User.kt @@ -0,0 +1,32 @@ +package com.coded.spring.ordering.model + +import jakarta.persistence.Entity +import jakarta.persistence.EnumType +import jakarta.persistence.Enumerated +import jakarta.persistence.GeneratedValue +import jakarta.persistence.GenerationType +import jakarta.persistence.Id +import jakarta.persistence.Table + +@Entity +@Table(name = "users") +data class User( + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + var id: Long? = null, + var name: String, + var age: Int, + + var username: String, + var password: String, + + @Enumerated(EnumType.STRING) + val role: Roles = Roles.USER + +){ + constructor() : this(null, "name", 0, "username", "password", Roles.USER) +} + +enum class Roles { + USER, ADMIN +} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/repository/ItemRepository.kt b/src/main/kotlin/com/coded/spring/ordering/repository/ItemRepository.kt index 13f7982..be73ebb 100644 --- a/src/main/kotlin/com/coded/spring/ordering/repository/ItemRepository.kt +++ b/src/main/kotlin/com/coded/spring/ordering/repository/ItemRepository.kt @@ -1,28 +1,8 @@ package com.coded.spring.ordering.repository -import jakarta.persistence.Entity -import jakarta.persistence.GeneratedValue -import jakarta.persistence.GenerationType -import jakarta.persistence.Id -import jakarta.persistence.ManyToOne -import jakarta.persistence.Table +import com.coded.spring.ordering.model.Item import org.springframework.data.jpa.repository.JpaRepository interface ItemRepository : JpaRepository -@Entity -@Table(name = "items") -data class Item( - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - val id: Long = 0, - - @ManyToOne - val order: com.coded.spring.ordering.repository.Order = Order(), - - val name: String = "", - - val quantity: Int = 1 -) { - constructor() : this(0, Order(), "", 1) -} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/repository/MenuItemRepository.kt b/src/main/kotlin/com/coded/spring/ordering/repository/MenuItemRepository.kt new file mode 100644 index 0000000..a8ffe20 --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/repository/MenuItemRepository.kt @@ -0,0 +1,6 @@ +package com.coded.spring.ordering.repository + +import com.coded.spring.ordering.model.MenuItem +import org.springframework.data.jpa.repository.JpaRepository + +interface MenuItemRepository : JpaRepository \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/repository/OrderRepository.kt b/src/main/kotlin/com/coded/spring/ordering/repository/OrderRepository.kt index 3d49e8c..0992979 100644 --- a/src/main/kotlin/com/coded/spring/ordering/repository/OrderRepository.kt +++ b/src/main/kotlin/com/coded/spring/ordering/repository/OrderRepository.kt @@ -1,24 +1,7 @@ package com.coded.spring.ordering.repository -import jakarta.persistence.Entity -import jakarta.persistence.GeneratedValue -import jakarta.persistence.GenerationType -import jakarta.persistence.Id -import jakarta.persistence.ManyToOne -import jakarta.persistence.Table +import com.coded.spring.ordering.model.Order import org.springframework.data.jpa.repository.JpaRepository interface OrderRepository : JpaRepository - -@Entity -@Table(name = "orders") -data class Order( - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - val id: Long = 0, - - @ManyToOne - val user: com.coded.spring.ordering.repository.User = User() -) { - constructor() : this(0, User()) -} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/repository/ProfileRepository.kt b/src/main/kotlin/com/coded/spring/ordering/repository/ProfileRepository.kt new file mode 100644 index 0000000..62b2efd --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/repository/ProfileRepository.kt @@ -0,0 +1,8 @@ +package com.coded.spring.ordering.repository + +import com.coded.spring.ordering.model.Profile +import org.springframework.data.jpa.repository.JpaRepository + +interface ProfileRepository : JpaRepository { + fun findByUserId(userId: Long): Profile? +} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/repository/UserRepository.kt b/src/main/kotlin/com/coded/spring/ordering/repository/UserRepository.kt index 5e26113..6b67c94 100644 --- a/src/main/kotlin/com/coded/spring/ordering/repository/UserRepository.kt +++ b/src/main/kotlin/com/coded/spring/ordering/repository/UserRepository.kt @@ -1,22 +1,10 @@ package com.coded.spring.ordering.repository -import jakarta.persistence.Entity -import jakarta.persistence.GeneratedValue -import jakarta.persistence.GenerationType -import jakarta.persistence.Id -import jakarta.persistence.Table -import org.springframework.data.jpa.repository.JpaRepository -interface UserRepository : JpaRepository +import com.coded.spring.ordering.model.User +import org.springframework.data.jpa.repository.JpaRepository -@Entity -@Table(name = "users") -data class User( - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - val id: Long = 0, - val username: String = "", - val age: Int = 0 -) { - constructor() : this(0, "", 0) -} \ No newline at end of file +interface UserRepository : JpaRepository{ + fun findByUsername(username: String): User? +} diff --git a/src/main/kotlin/com/coded/spring/ordering/service/ItemService.kt b/src/main/kotlin/com/coded/spring/ordering/service/ItemService.kt index 13a4494..aa77176 100644 --- a/src/main/kotlin/com/coded/spring/ordering/service/ItemService.kt +++ b/src/main/kotlin/com/coded/spring/ordering/service/ItemService.kt @@ -1,6 +1,6 @@ package com.coded.spring.ordering.service -import com.coded.spring.ordering.repository.Item +import com.coded.spring.ordering.model.Item import com.coded.spring.ordering.repository.ItemRepository import com.coded.spring.ordering.repository.OrderRepository import org.springframework.stereotype.Service diff --git a/src/main/kotlin/com/coded/spring/ordering/service/MenuService.kt b/src/main/kotlin/com/coded/spring/ordering/service/MenuService.kt new file mode 100644 index 0000000..3d9386b --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/service/MenuService.kt @@ -0,0 +1,14 @@ +package com.coded.spring.ordering.service + +import com.coded.spring.ordering.model.MenuItem +import com.coded.spring.ordering.repository.MenuItemRepository +import org.springframework.stereotype.Service + +@Service +class MenuService( + private val menuItemRepository: MenuItemRepository +) { + fun getAllMenuItems(): List = menuItemRepository.findAll() + + fun addMenuItem(menuItem: MenuItem): MenuItem = menuItemRepository.save(menuItem) +} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/service/OrderService.kt b/src/main/kotlin/com/coded/spring/ordering/service/OrderService.kt index a679c78..a8214c4 100644 --- a/src/main/kotlin/com/coded/spring/ordering/service/OrderService.kt +++ b/src/main/kotlin/com/coded/spring/ordering/service/OrderService.kt @@ -1,6 +1,6 @@ package com.coded.spring.ordering.service -import com.coded.spring.ordering.repository.Order +import com.coded.spring.ordering.model.Order import com.coded.spring.ordering.repository.OrderRepository import com.coded.spring.ordering.repository.UserRepository import org.springframework.stereotype.Service diff --git a/src/main/kotlin/com/coded/spring/ordering/service/ProfilesService.kt b/src/main/kotlin/com/coded/spring/ordering/service/ProfilesService.kt new file mode 100644 index 0000000..78e833e --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/service/ProfilesService.kt @@ -0,0 +1,46 @@ +package com.coded.spring.ordering.service + +import com.coded.spring.ordering.model.Profile +import com.coded.spring.ordering.model.User +import com.coded.spring.ordering.repository.ProfileRepository +import com.coded.spring.ordering.repository.UserRepository +import org.springframework.http.HttpStatus +import org.springframework.stereotype.Service +import org.springframework.web.server.ResponseStatusException + +@Service +class ProfileService( + private val profileRepository: ProfileRepository, + private val userRepository: UserRepository +) { + + fun createOrUpdateProfile(userId: Long, firstName: String, lastName: String, phoneNumber: String): Profile { + validateInputs(firstName, lastName, phoneNumber) + + val user: User = userRepository.findById(userId) + .orElseThrow { ResponseStatusException(HttpStatus.NOT_FOUND, "User not found") } + + val existing = profileRepository.findByUserId(userId) + return if (existing != null) { + val updated = existing.copy(firstName = firstName, lastName = lastName, phoneNumber = phoneNumber) + profileRepository.save(updated) + } else { + val newProfile = Profile(user = user, firstName = firstName, lastName = lastName, phoneNumber = phoneNumber) + profileRepository.save(newProfile) + } + } + + fun getProfile(userId: Long): Profile? = profileRepository.findByUserId(userId) + + private fun validateInputs(firstName: String, lastName: String, phoneNumber: String) { + if (!firstName.matches(Regex("^[A-Za-z]+$"))) { + throw ResponseStatusException(HttpStatus.BAD_REQUEST, "First name must contain letters only") + } + if (!lastName.matches(Regex("^[A-Za-z]+$"))) { + throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Last name must contain letters only") + } + if (!phoneNumber.matches(Regex("^\\d{8}$"))) { + throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Phone number must be exactly 8 digits with no letters") + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/service/UserService.kt b/src/main/kotlin/com/coded/spring/ordering/service/UserService.kt index b2afda8..77715d6 100644 --- a/src/main/kotlin/com/coded/spring/ordering/service/UserService.kt +++ b/src/main/kotlin/com/coded/spring/ordering/service/UserService.kt @@ -1,11 +1,11 @@ package com.coded.spring.ordering.service -import com.coded.spring.ordering.repository.User +import com.coded.spring.ordering.model.User import com.coded.spring.ordering.repository.UserRepository import org.springframework.stereotype.Service @Service class UserService(private val userRepository: UserRepository) { - fun createUser(user: User): User = userRepository.save(user) fun getAllUsers(): List = userRepository.findAll() + } \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 3ec1f6b..93145b9 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -4,4 +4,5 @@ spring.datasource.url=jdbc:postgresql://localhost:8080/orders spring.datasource.username=postgres spring.datasource.password=12345678 spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect +spring.jpa.hibernate.ddl-auto=update server.port=8081 \ No newline at end of file From 878528a9419fd59f1bba3d1ec43c42da9ab5a1ae Mon Sep 17 00:00:00 2001 From: hussainjg Date: Sun, 27 Apr 2025 20:16:12 +0300 Subject: [PATCH 5/7] UPdated --- pom.xml | 63 ++++++++++++++++++ .../coded/spring/ordering/InitUserRunner.kt | 2 +- .../coded/spring/ordering/LoggingFilter.kt | 37 +++++++++++ .../ordering/authentication/SecurityConfig.kt | 6 +- .../controller/HelloworldController.kt | 30 +++++++++ .../ordering/controller/OrderController.kt | 3 + src/main/resources/application.properties | 2 +- .../coded/spring/ordering/ApplicationTests.kt | 37 ++++++++++- .../spring/ordering/steps/StepDefinitions.kt | 65 +++++++++++++++++++ src/test/resources/features/hello.feature | 18 +++++ 10 files changed, 257 insertions(+), 6 deletions(-) create mode 100644 src/main/kotlin/com/coded/spring/ordering/LoggingFilter.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/controller/HelloworldController.kt create mode 100644 src/test/kotlin/com/coded/spring/ordering/steps/StepDefinitions.kt create mode 100644 src/test/resources/features/hello.feature diff --git a/pom.xml b/pom.xml index 49c0d96..ce077f5 100644 --- a/pom.xml +++ b/pom.xml @@ -73,6 +73,7 @@ org.postgresql postgresql + compile org.springframework.boot @@ -95,6 +96,68 @@ runtime 0.11.5 + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-starter-test + test + + + org.jetbrains.kotlin + kotlin-test-junit5 + test + + + com.h2database + h2 + test + + + io.cucumber + cucumber-java + 7.11.2 + test + + + io.cucumber + cucumber-junit + 7.11.2 + test + + + io.rest-assured + rest-assured + 5.3.0 + test + + + io.rest-assured + json-path + 5.3.0 + test + + + io.rest-assured + json-schema-validator + 5.3.0 + test + + + org.junit.jupiter + junit-jupiter-api + 5.10.0 + test + + + org.junit.jupiter + junit-jupiter-engine + 5.10.0 + test + diff --git a/src/main/kotlin/com/coded/spring/ordering/InitUserRunner.kt b/src/main/kotlin/com/coded/spring/ordering/InitUserRunner.kt index 1f87083..61e8ff6 100644 --- a/src/main/kotlin/com/coded/spring/ordering/InitUserRunner.kt +++ b/src/main/kotlin/com/coded/spring/ordering/InitUserRunner.kt @@ -9,7 +9,7 @@ import org.springframework.boot.runApplication import org.springframework.context.annotation.Bean import org.springframework.security.crypto.password.PasswordEncoder -@SpringBootApplication +// @SpringBootApplication class InitUserRunner { @Bean fun initUsers(userRepository: UserRepository, passwordEncoder: PasswordEncoder) = CommandLineRunner { diff --git a/src/main/kotlin/com/coded/spring/ordering/LoggingFilter.kt b/src/main/kotlin/com/coded/spring/ordering/LoggingFilter.kt new file mode 100644 index 0000000..ac5baa8 --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/LoggingFilter.kt @@ -0,0 +1,37 @@ +package com.coded.spring.ordering + +import jakarta.servlet.FilterChain +import jakarta.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletResponse +import org.springframework.stereotype.Component +import org.springframework.web.filter.OncePerRequestFilter +import org.springframework.web.util.ContentCachingRequestWrapper +import org.springframework.web.util.ContentCachingResponseWrapper + +@Component +class LoggingFilter: OncePerRequestFilter(){ + override fun doFilterInternal( + request: HttpServletRequest, + response: HttpServletResponse, + filterChain: FilterChain + ) { + val cachedRequest = ContentCachingRequestWrapper(request) + val cachedResponse = ContentCachingResponseWrapper(response) + + filterChain.doFilter(cachedRequest, cachedResponse) + + logRequest(cachedRequest) + logResponse(cachedResponse) + cachedResponse.copyBodyToResponse() + } + + private fun logRequest(request: ContentCachingRequestWrapper) { + val requestBody = String(request.contentAsByteArray) + logger.info("Request: method=${request.method}, uri=${request.requestURI}, body=$requestBody") + } + + private fun logResponse(response: ContentCachingResponseWrapper) { + val responseBody = String(response.contentAsByteArray) + logger.info("Response: status=${response.status}, body=$responseBody") + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/authentication/SecurityConfig.kt b/src/main/kotlin/com/coded/spring/ordering/authentication/SecurityConfig.kt index 4a199fd..f184fee 100644 --- a/src/main/kotlin/com/coded/spring/ordering/authentication/SecurityConfig.kt +++ b/src/main/kotlin/com/coded/spring/ordering/authentication/SecurityConfig.kt @@ -29,13 +29,15 @@ class SecurityConfig( http.csrf { it.disable() } .authorizeHttpRequests { it - .requestMatchers("/auth/**").permitAll() .requestMatchers("/users/create").permitAll() + .requestMatchers("/auth/**").permitAll() + .requestMatchers("/hello").permitAll() + .requestMatchers("/users/getAll").permitAll() .requestMatchers("/users/**").hasRole("ADMIN") .requestMatchers("/profile/**").authenticated() .requestMatchers("/menu/**").authenticated() - .anyRequest().authenticated() + .anyRequest().permitAll() } .sessionManagement { it.sessionCreationPolicy(SessionCreationPolicy.STATELESS) diff --git a/src/main/kotlin/com/coded/spring/ordering/controller/HelloworldController.kt b/src/main/kotlin/com/coded/spring/ordering/controller/HelloworldController.kt new file mode 100644 index 0000000..10ca3e9 --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/controller/HelloworldController.kt @@ -0,0 +1,30 @@ +package com.coded.spring.ordering.controller + +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RestController + + @RestController + class HelloWorldController { + + @GetMapping("/hello") + fun helloWorld(): String { + return "Hello World Welcome to my server!" + } + + @PostMapping("/my-name") + fun myName(@RequestBody request: NameRequest): NameResponse { + return NameResponse(id = 1, name = request.name) + } + + + data class NameRequest( + val name: String + ) + + data class NameResponse( + val id: Int, + val name: String + ) + } \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/controller/OrderController.kt b/src/main/kotlin/com/coded/spring/ordering/controller/OrderController.kt index c258e50..151ed8b 100644 --- a/src/main/kotlin/com/coded/spring/ordering/controller/OrderController.kt +++ b/src/main/kotlin/com/coded/spring/ordering/controller/OrderController.kt @@ -1,7 +1,9 @@ package com.coded.spring.ordering.controller +import com.coded.spring.ordering.model.Item import com.coded.spring.ordering.model.Order import com.coded.spring.ordering.service.OrderService +import org.springframework.http.HttpEntity import org.springframework.web.bind.annotation.* @RestController @@ -17,4 +19,5 @@ class OrderController(private val orderService: OrderService) { fun getAllOrders(): List { return orderService.getAllOrders() } + } \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 93145b9..e736a3f 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -5,4 +5,4 @@ spring.datasource.username=postgres spring.datasource.password=12345678 spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect spring.jpa.hibernate.ddl-auto=update -server.port=8081 \ No newline at end of file +server.port=8081 diff --git a/src/test/kotlin/com/coded/spring/ordering/ApplicationTests.kt b/src/test/kotlin/com/coded/spring/ordering/ApplicationTests.kt index b2e2320..70c6c93 100644 --- a/src/test/kotlin/com/coded/spring/ordering/ApplicationTests.kt +++ b/src/test/kotlin/com/coded/spring/ordering/ApplicationTests.kt @@ -1,13 +1,46 @@ package com.coded.spring.ordering +import com.coded.spring.ordering.model.User +import com.coded.spring.ordering.repository.UserRepository +import com.fasterxml.jackson.databind.ObjectMapper import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest +import org.springframework.boot.test.web.client.TestRestTemplate +import org.springframework.boot.test.web.client.postForEntity +import org.springframework.http.HttpEntity +import org.springframework.http.HttpHeaders +import org.springframework.http.HttpStatus +import org.springframework.http.MediaType +import kotlin.test.assertEquals -@SpringBootTest +@SpringBootTest(classes = [Application::class], webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) class ApplicationTests { + @Autowired + lateinit var restTemplate: TestRestTemplate + + @Autowired + lateinit var userRepository: UserRepository + @Test - fun contextLoads() { + fun helloWorld() { + val result = restTemplate.getForEntity("/hello", String::class.java) + val expected = "Hello World" + assertEquals(expected, actual = result.body) + assertEquals(HttpStatus.OK, actual = result?.statusCode) } + @Test + fun testCreateUser() { + + val user = User(null, name = "Test", 17 ,username = "t1estusehr123", password = "test123") + val result = restTemplate.postForEntity("/users/create",user ,String::class.java) + assertEquals(HttpStatus.OK, actual = result?.statusCode) + } + + @Test + fun contextLoads() { + + } } diff --git a/src/test/kotlin/com/coded/spring/ordering/steps/StepDefinitions.kt b/src/test/kotlin/com/coded/spring/ordering/steps/StepDefinitions.kt new file mode 100644 index 0000000..2564f5a --- /dev/null +++ b/src/test/kotlin/com/coded/spring/ordering/steps/StepDefinitions.kt @@ -0,0 +1,65 @@ +package com.coded.spring.ordering.steps + +import io.cucumber.java.en.Given +import io.cucumber.java.en.When +import io.cucumber.java.en.Then +import io.restassured.RestAssured +import io.restassured.response.Response +import io.restassured.http.ContentType +import org.springframework.boot.test.web.server.LocalServerPort +import org.hamcrest.MatcherAssert.assertThat +import org.skyscreamer.jsonassert.JSONAssert +import org.hamcrest.Matchers.equalTo +import org.springframework.test.context.ContextConfiguration + +@ContextConfiguration +class StepDefinitions { + + @LocalServerPort + private var port: Int = 8081 + + private lateinit var response: Response + private var requestBody: String = "" + + @Given("the client sets the request body to") + fun setRequestBody(body: String) { + requestBody = body + } + + @When("the client sends a GET request to {string}") + fun sendGetRequest(endpoint: String) { + response = RestAssured + .given() + .port(port) + .`when`() + .get(endpoint) + } + + @When("the client sends a POST request to {string}") + fun sendPostRequest(endpoint: String) { + response = RestAssured + .given() + .port(port) + .contentType(ContentType.JSON) + .body(requestBody) + .`when`() + .post(endpoint) + } + + @Then("the response status should be {int}") + fun checkStatus(expectedStatus: Int) { + assertThat(response.statusCode, equalTo(expectedStatus)) + } + + @Then("the response body should be {string}") + fun checkResponseBody(expectedBody: String) { + val actualBody = response.body.asString() + assertThat(actualBody, equalTo(expectedBody)) + } + + @Then("the response body should be") + fun checkResponseBodyJson(expectedJson: String) { + val actualJson = response.body.asString() + JSONAssert.assertEquals(expectedJson, actualJson, true) + } +} \ No newline at end of file diff --git a/src/test/resources/features/hello.feature b/src/test/resources/features/hello.feature new file mode 100644 index 0000000..102779c --- /dev/null +++ b/src/test/resources/features/hello.feature @@ -0,0 +1,18 @@ +Feature: My Name Endpoint + + Scenario: Client sends a POST request to /my-name with a name + Given the client sets the request body to + """ + { + "name": "Hussain" + } + """ + When the client sends a POST request to "/my-name" + Then the response status should be 200 + And the response body should be + """ + { + "id": 1, + "name": "Hussain" + } + """ \ No newline at end of file From 982245ad8fcd5282c239d8ae23c2de66756b3f12 Mon Sep 17 00:00:00 2001 From: hussainjg Date: Mon, 28 Apr 2025 20:24:56 +0300 Subject: [PATCH 6/7] Updated 28-4-2025 --- pom.xml | 10 ++++++++ .../coded/spring/ordering/AppProperties.kt | 13 ++++++++++ .../com/coded/spring/ordering/Application.kt | 7 ++++++ .../controller/HelloworldController.kt | 20 ++++++++++++++-- .../ordering/controller/MenuController.kt | 19 +++++++++++++-- .../com/coded/spring/ordering/model/Pet.kt | 8 +++++++ .../coded/spring/ordering/pets/PetsClient.kt | 16 +++++++++++++ .../spring/ordering/pets/PetsProvider.kt | 24 +++++++++++++++++++ .../coded/spring/ordering/pets/PetsService.kt | 10 ++++++++ src/main/resources/application.properties | 1 + src/main/resources/application.yaml | 4 ++++ .../coded/spring/ordering/ApplicationTests.kt | 4 ---- 12 files changed, 128 insertions(+), 8 deletions(-) create mode 100644 src/main/kotlin/com/coded/spring/ordering/AppProperties.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/model/Pet.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/pets/PetsClient.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/pets/PetsProvider.kt create mode 100644 src/main/kotlin/com/coded/spring/ordering/pets/PetsService.kt create mode 100644 src/main/resources/application.yaml diff --git a/pom.xml b/pom.xml index ce077f5..7bdd9c7 100644 --- a/pom.xml +++ b/pom.xml @@ -158,6 +158,16 @@ 5.10.0 test + + com.hazelcast + hazelcast + 5.5.0 + + + org.springdoc + springdoc-openapi-starter-webmvc-api + 2.6.0 + diff --git a/src/main/kotlin/com/coded/spring/ordering/AppProperties.kt b/src/main/kotlin/com/coded/spring/ordering/AppProperties.kt new file mode 100644 index 0000000..c811817 --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/AppProperties.kt @@ -0,0 +1,13 @@ +package com.coded.spring.ordering + +import org.springframework.boot.context.properties.ConfigurationProperties +import org.springframework.context.annotation.Configuration + +@Configuration +@ConfigurationProperties +class AppProperties { + lateinit var companyName: String + var festiveMode: Boolean = false + var festiveMessage: String = "Eidkom Mubarak" + var festiveDiscount: Int = 20 +} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/Application.kt b/src/main/kotlin/com/coded/spring/ordering/Application.kt index 8554e49..f00e5d9 100644 --- a/src/main/kotlin/com/coded/spring/ordering/Application.kt +++ b/src/main/kotlin/com/coded/spring/ordering/Application.kt @@ -1,5 +1,8 @@ package com.coded.spring.ordering +import com.hazelcast.config.Config; +import com.hazelcast.core.Hazelcast +import com.hazelcast.core.HazelcastInstance import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -8,4 +11,8 @@ class Application fun main(args: Array) { runApplication(*args) + helloWorldConfig.getMapConfig("pets").setTimeToLiveSeconds(5) } + +val helloWorldConfig = Config("hello-world-cache") +val serverCache: HazelcastInstance = Hazelcast.newHazelcastInstance(helloWorldConfig) \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/controller/HelloworldController.kt b/src/main/kotlin/com/coded/spring/ordering/controller/HelloworldController.kt index 10ca3e9..c35758c 100644 --- a/src/main/kotlin/com/coded/spring/ordering/controller/HelloworldController.kt +++ b/src/main/kotlin/com/coded/spring/ordering/controller/HelloworldController.kt @@ -1,12 +1,17 @@ package com.coded.spring.ordering.controller +import com.coded.spring.ordering.AppProperties +import com.coded.spring.ordering.pets.PetsService import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.RequestBody import org.springframework.web.bind.annotation.RestController @RestController - class HelloWorldController { + class HelloWorldController ( + private val petsProvider: PetsService, + private val appProperties: AppProperties + ){ @GetMapping("/hello") fun helloWorld(): String { @@ -17,7 +22,18 @@ import org.springframework.web.bind.annotation.RestController fun myName(@RequestBody request: NameRequest): NameResponse { return NameResponse(id = 1, name = request.name) } - + @GetMapping("/pets") + fun getPets(): String { + return petsProvider.listPets().toString().replace("[", "").replace("]", "") + } + @GetMapping("/welcome") + fun welcome(): String { + return if (appProperties.festiveMode) { + appProperties.festiveMessage + } else { + "Welcome to Online Ordering by ${appProperties.companyName}" + } + } data class NameRequest( val name: String diff --git a/src/main/kotlin/com/coded/spring/ordering/controller/MenuController.kt b/src/main/kotlin/com/coded/spring/ordering/controller/MenuController.kt index e9eca2d..0d7eb8d 100644 --- a/src/main/kotlin/com/coded/spring/ordering/controller/MenuController.kt +++ b/src/main/kotlin/com/coded/spring/ordering/controller/MenuController.kt @@ -1,17 +1,32 @@ package com.coded.spring.ordering.controller +import com.coded.spring.ordering.AppProperties import com.coded.spring.ordering.model.MenuItem import com.coded.spring.ordering.service.MenuService +import com.coded.spring.ordering.service.OrderService import org.springframework.web.bind.annotation.* +import kotlin.div + @RestController @RequestMapping("/menu") class MenuController( - private val menuService: MenuService + private val menuService: MenuService, + private val appProperties: AppProperties, + private val menuItems: List ) { @GetMapping - fun getMenu(): List = menuService.getAllMenuItems() + fun getMenu(): List { + return if (appProperties.festiveMode) { + menuItems.map { + val discountedPrice = it.price * (1 - appProperties.festiveDiscount / 100.0) + it.copy(price = String.format("%.2f", discountedPrice).toDouble()) + } + } else { + menuItems + } + } @PostMapping fun addMenuItem(@RequestBody menuItem: MenuItem): MenuItem { diff --git a/src/main/kotlin/com/coded/spring/ordering/model/Pet.kt b/src/main/kotlin/com/coded/spring/ordering/model/Pet.kt new file mode 100644 index 0000000..70751b7 --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/model/Pet.kt @@ -0,0 +1,8 @@ +package com.coded.spring.ordering.model + +import java.io.Serializable + +data class Pet( + val name: String, + val type: String +) : Serializable \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/pets/PetsClient.kt b/src/main/kotlin/com/coded/spring/ordering/pets/PetsClient.kt new file mode 100644 index 0000000..9c1ee1f --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/pets/PetsClient.kt @@ -0,0 +1,16 @@ +package com.coded.spring.ordering.pets + +import com.coded.spring.ordering.model.Pet +import org.springframework.stereotype.Component + +@Component +class PetsClient { + + fun getPets(): List { + return listOf( + Pet(name = "Bella", "Dog"), + Pet(name = "Charlie", "Cat"), + Pet(name = "Luna", "Bird") + ) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/pets/PetsProvider.kt b/src/main/kotlin/com/coded/spring/ordering/pets/PetsProvider.kt new file mode 100644 index 0000000..0e06d13 --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/pets/PetsProvider.kt @@ -0,0 +1,24 @@ +package com.coded.spring.ordering.pets + +import com.coded.spring.ordering.model.Pet +import com.coded.spring.ordering.serverCache +import jakarta.inject.Named + +@Named +class PetsProvider( + private val client: PetsClient) { + + fun getPets(): List { + val cachedPets = petsCache["pets"] + if (cachedPets?.size == 0 || cachedPets == null) { + println("No pets found, caching new data...") + val pets = client.getPets() + petsCache.put("pets", pets) + return pets + } + println("returning ${cachedPets.size} pets") + return petsCache["pets"] ?: listOf() + } +} + +val petsCache = serverCache.getMap>("pets") \ No newline at end of file diff --git a/src/main/kotlin/com/coded/spring/ordering/pets/PetsService.kt b/src/main/kotlin/com/coded/spring/ordering/pets/PetsService.kt new file mode 100644 index 0000000..64b0c4b --- /dev/null +++ b/src/main/kotlin/com/coded/spring/ordering/pets/PetsService.kt @@ -0,0 +1,10 @@ +package com.coded.spring.ordering.pets + +import com.coded.spring.ordering.model.Pet +import jakarta.inject.Named + +@Named +class PetsService(private val petsProvider: PetsProvider) { + + fun listPets() : List = petsProvider.getPets() +} \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index e736a3f..aa7ab6c 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -6,3 +6,4 @@ spring.datasource.password=12345678 spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect spring.jpa.hibernate.ddl-auto=update server.port=8081 +springdoc.api-docs.path=/api-docs diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml new file mode 100644 index 0000000..05c1f9c --- /dev/null +++ b/src/main/resources/application.yaml @@ -0,0 +1,4 @@ +company-name: NBK FullStack course +festive-mode: false +festive-message: "Eidkom Mubarak" +festive-discount: 20 \ No newline at end of file diff --git a/src/test/kotlin/com/coded/spring/ordering/ApplicationTests.kt b/src/test/kotlin/com/coded/spring/ordering/ApplicationTests.kt index 70c6c93..955cf14 100644 --- a/src/test/kotlin/com/coded/spring/ordering/ApplicationTests.kt +++ b/src/test/kotlin/com/coded/spring/ordering/ApplicationTests.kt @@ -7,11 +7,7 @@ import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.boot.test.web.client.TestRestTemplate -import org.springframework.boot.test.web.client.postForEntity -import org.springframework.http.HttpEntity -import org.springframework.http.HttpHeaders import org.springframework.http.HttpStatus -import org.springframework.http.MediaType import kotlin.test.assertEquals @SpringBootTest(classes = [Application::class], webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) From b91e2d65bbc505007333cf817316ec3df1d50f76 Mon Sep 17 00:00:00 2001 From: hussainjg Date: Thu, 1 May 2025 16:46:52 +0300 Subject: [PATCH 7/7] Backup --- .DS_Store | Bin 6148 -> 6148 bytes pom.xml | 136 ++++++++++-------- src/.DS_Store | Bin 6148 -> 6148 bytes src/main/.DS_Store | Bin 6148 -> 6148 bytes src/main/kotlin/.DS_Store | Bin 6148 -> 6148 bytes src/main/kotlin/com/.DS_Store | Bin 6148 -> 6148 bytes src/main/kotlin/com/coded/.DS_Store | Bin 6148 -> 6148 bytes src/main/kotlin/com/coded/spring/.DS_Store | Bin 6148 -> 8196 bytes src/test/.DS_Store | Bin 0 -> 6148 bytes src/test/kotlin/.DS_Store | Bin 0 -> 6148 bytes src/test/kotlin/com/.DS_Store | Bin 0 -> 6148 bytes src/test/kotlin/com/coded/.DS_Store | Bin 0 -> 6148 bytes src/test/kotlin/com/coded/spring/.DS_Store | Bin 0 -> 6148 bytes .../com/coded/spring/ordering/.DS_Store | Bin 0 -> 6148 bytes 14 files changed, 73 insertions(+), 63 deletions(-) create mode 100644 src/test/.DS_Store create mode 100644 src/test/kotlin/.DS_Store create mode 100644 src/test/kotlin/com/.DS_Store create mode 100644 src/test/kotlin/com/coded/.DS_Store create mode 100644 src/test/kotlin/com/coded/spring/.DS_Store create mode 100644 src/test/kotlin/com/coded/spring/ordering/.DS_Store diff --git a/.DS_Store b/.DS_Store index bff4f9e7e7036fe82ce14578459537e287057783..a27e05c194100fda628606322bc1c2e794858a0f 100644 GIT binary patch delta 20 bcmZoMXffC@jfvgZ)I>+Y#CY>urgTvNL1qQj delta 20 bcmZoMXffC@jfvgF&|F8s*mCn+rgTvNL4gI@ diff --git a/pom.xml b/pom.xml index 7bdd9c7..935bb37 100644 --- a/pom.xml +++ b/pom.xml @@ -1,173 +1,183 @@ - 4.0.0 + org.springframework.boot spring-boot-starter-parent 3.4.4 - + - com.hussain - helloworld + + com.coded.spring + Ordering 0.0.1-SNAPSHOT - helloworld - My First Spring Boot - - - - - - - - - - - - - + Kotlin.SpringbootV2 + Kotlin.SpringbootV2 + 21 1.9.25 + - - org.springframework.boot - spring-boot-starter - + org.springframework.boot spring-boot-starter-web - - org.jetbrains.kotlin - kotlin-reflect - - - org.jetbrains.kotlin - kotlin-stdlib - org.springframework.boot - spring-boot-starter-test - test + spring-boot-starter-data-jpa + + - org.jetbrains.kotlin - kotlin-test-junit5 - test + org.springframework.boot + spring-boot-starter-security + + - jakarta.inject - jakarta.inject-api + org.springframework.security + spring-security-crypto + + - org.springframework.boot - spring-boot-starter-data-jpa + org.postgresql + postgresql + runtime + com.h2database h2 + test + + - org.postgresql - postgresql - compile + org.jetbrains.kotlin + kotlin-reflect + - org.springframework.boot - spring-boot-starter-security + org.jetbrains.kotlin + kotlin-stdlib + + + com.fasterxml.jackson.module + jackson-module-kotlin + + + io.jsonwebtoken jjwt-api 0.11.5 + io.jsonwebtoken jjwt-impl runtime 0.11.5 + io.jsonwebtoken jjwt-jackson runtime 0.11.5 + + - org.springframework.boot - spring-boot-starter-test - test + org.springdoc + springdoc-openapi-starter-webmvc-ui + 2.5.0 + + + + jakarta.inject + jakarta.inject-api + + + + + com.hazelcast + hazelcast + 5.5.0 + + + org.springframework.boot spring-boot-starter-test test + org.jetbrains.kotlin kotlin-test-junit5 test - - com.h2database - h2 - test - + io.cucumber cucumber-java 7.11.2 test + io.cucumber cucumber-junit 7.11.2 test + io.rest-assured rest-assured 5.3.0 test + io.rest-assured json-path 5.3.0 test + io.rest-assured json-schema-validator 5.3.0 test + org.junit.jupiter junit-jupiter-api 5.10.0 test + org.junit.jupiter junit-jupiter-engine 5.10.0 test - - com.hazelcast - hazelcast - 5.5.0 - - - org.springdoc - springdoc-openapi-starter-webmvc-api - 2.6.0 - + diff --git a/src/.DS_Store b/src/.DS_Store index e9086dd2450e1e125231a2d219da0d13c121f451..e3ca6d05e3e1d54d796662f64e67301427934abd 100644 GIT binary patch delta 119 zcmZoMXfc=|#>B!ku~2NHo+2a9#(>?7i&&T#c_#BP^{^Y8n&>E)7*C$hbaS!uWRnJ5cG2}3GFF+)jNa8X`PeqK5Q0|Vp6LTkp&>>T_YKw~$5Wd6=PnP0?_gOP!O N2`J03IYML&GXOn<9ftq_ delta 82 zcmZoMXfc=|#>B)qu~2NHo+2aH#(>?7j9im>SbEq^49#^Ej4db6XSq4qgDrovD2EWs k#0I|2>>T_YKpmR}IlePb<`;3~U;qL}1_qYR5h81t0cRN#Qvd(} diff --git a/src/main/.DS_Store b/src/main/.DS_Store index 47dc945d310e4618091447c847e7d91cc1a929cd..aebc195c26c99fddba40580fbe93c7bac2b7a067 100644 GIT binary patch delta 79 zcmZoMXfc@J&&abeU^g=(&tx8!3GBwECOQfx#*-Jbe4i}C(tyNwn9Rr~Jb4ytFNo$T Y3ogpb$|1t#@PT1IEql9Dn%% DQ8W)l diff --git a/src/main/kotlin/.DS_Store b/src/main/kotlin/.DS_Store index cd008e9d166984efb50f8c8a0141358e897655c7..307f3d1f1ad557d5b525321bba1120fddda9c869 100644 GIT binary patch delta 20 bcmZoMXffC@jfvgZ)I>+Y#CY>urgTvNL1qQj delta 20 bcmZoMXffC@jfvgF&|F8s*mCn+rgTvNL4gI@ diff --git a/src/main/kotlin/com/.DS_Store b/src/main/kotlin/com/.DS_Store index b3d2d66aee3c78f5fdcd66cc1545c926fa9d6583..83356c811412b23a903e390c2955156b4e0f0cbc 100644 GIT binary patch delta 20 bcmZoMXffC@i;3OX)I>+Y#CY>Uresk7L8=AW delta 20 bcmZoMXffC@i;3OD&|F8s*mCniresk7LB$2$ diff --git a/src/main/kotlin/com/coded/.DS_Store b/src/main/kotlin/com/coded/.DS_Store index ccf8a4612f6ae848d527e905b9ca099f06859a39..9376609005de6944750577299746eb9c0944a88a 100644 GIT binary patch delta 20 bcmZoMXffC@hl$+Y#CY>!rbJNyLCgi) delta 20 bcmZoMXffC@hl$<9&|F8s*mCn?rbJNyLFWbF diff --git a/src/main/kotlin/com/coded/spring/.DS_Store b/src/main/kotlin/com/coded/spring/.DS_Store index 4b248e646192de301e4bf4eeca433debc7b39e91..6636002d72c6bf7239864ad13fe2ea5681b22566 100644 GIT binary patch literal 8196 zcmeHMTWl0n7(U;$!0bTF00R^k=;Ah93-*EqQk3lt3qlILQ_y90XJ{u(XO^AWEm|8J zH8Fz57av5t#V2DTFGleaeZtF=ifKrYL`{6rL`-}_6CeD~oM{8SBtCc{VNNpVKj-}a ze=gsA|D66?#u%ClMlE9%j4_!WF4cup%~H6YKQoFHj&LQ&pRqi%n8OA$BVKNXbugg}JA9f<({J|yVjG8M{kA%jl`RY3|svXq8{ zLT$$4og9cgw8j^PEqT|yzp zcr@-x*FbY7#oYp%aivscBW6-!;X7K90lR$fR#-<+F9z$ zY}&c(!P>5@I~@Ktv0`vm8?V?R&R&w3Jp0wjv&R%=k=EPW*MB6fss+#NG;Q6tie{_s zn_gO7>=6+AvaWL|Zx#uFzN~8(h8@x@$?A5tK*na1ZFgCZn%;nZy4yVM^LD=O5 z@3#a#{T5Bbm1%V;pQe`0JJ+18r4o#FVR+lVYrYQpi zrQ=&CEHmFTVj2F>5#7t0j$t{2eMQT&GPc?6=)>j`RLil6l@+VXwYausQZ?O0R+Dmn zA!D5?SpFly8kGr6IcCr~4!Qw)hk+$t!GSIHDbbT$4*7-D~i*q4~B!gmnm95y})5Qq8E;(nl$ZU zzU%?r^E+~;LtFYHT)T~Q1KyCHH#2t8V%kRjdQ0q!}49O4A4ku9kP6cPuOG_ zrZG`ov1;YvPVS*vPSGOH6aIqw>Nm11CsUgR^#WLvsT$GKgqW)N{T652=r(I-$Jijt zu~GIEJI7vP=h<8A9rg*k#J*%#*fsVY`=0&4erCV18vrDfVjjw|5>;4_4cLfU+=u(I z2kkhB4jjT^3?L018DwE24<7{-@i?BwGdP2@cmc2ARlJ5baSo#+X;kiTII5XN{lu z-n|dB@B6>w=W1CPG0Rs}R&Cl=zhif5idlk+lkB^h(*cohp?^T+;MGqfA!pNF@zu)O zxniq_BEUQ?Qy|9F1;Torl9VX|)On)2UfC!U_tp8LyCuF=rf5^8psUox>tYmBYKiD> zi8sV#6{53CX^c^HsimU3I=+W=Ea=3W$9!-(767Ntb&qJroDZFB$re_QM|+C+pvguuUp07_fCTAOL^ zxxP?5*G|xLoE~1d-MEl}3su~Nj|b^E$*F%BQacgqQlT6dk~CEQ^B)4l-_OzgAKm|V H^!@)ApYDP8 delta 128 zcmZp1XfcprU|?W$DortDU=RQ@Ie-{MGjUEV6q~50$jG)aU^gQp+hiVrDeNYO<~j<- zmXntYly3emCcwC{;WqPPb`B0fW}prr5a0$9t{}}D3%@f@=9h5S5Z-O8-BN@c6nYGJEm&<8#Y>3w1&ruHr6#0kXv~%-HHT8jSzpK}@p+ut z-5i1eZz6UEcE8#A+0A^A{b7u8cNrcsW--PDG(?U{ji9;K)iA+`T+I=&B*@cw5X+!u zqQ7XuZ{KD!CRxT}R{j2uU>-+lHW+;JMzgiG-4<=p6%XFC%)QLdmZ|G6?r?N1WgL{c zAKXOKd}8fh$RzWlWV%oZQ8=zC9YAuKV`t z>}Y`c$$H%pd;16HSCd)%lE^nrBnQrw>=-QJ9h6EbbL!7+6Enig+}mzaGeUM zQ@MF!aGefz+r&8r3ynIRakVncV^%I7FI=q-c3Xur?r5Z*7$63!3^eu7!t?(Uewo@w zel>+g!~iky&lupXu{U<1D08-cD-X|F8`>i@6pSlS0Rg>o34j6aBR%ERej9a&a|{+5 UaTc_zbU?ZYC_<V%LnVvlnB~YkeV~#OLvx zBn5}P7IEi5@}1wL`Jnk>jB#%s9WdrF#soA(j!K1~yE3$4lMy+NF`I;m3c>maCpPxi z0l&S*9+_g}F#rDjNj%HC-A}$zt8Z>KL_@U1z5lFoKMS(?%nPQsXk96lgry#Y*YPMH zIy>ho&4M@`O?5#WjUeUjCQc)jdupCWGhOSOfM|;5&}lCgy`z3d_IoGGj$E7`c2PfG zE}LR^Z~yFa_>zoM^=9bgz_ylcizU2+VpsF(Pt!!DPv9xD%Pc}-fEXYKh=KKHz@7`D zwca$)>WKkjpn?J1A0#wH*J5E%ZynI#^%>)JL=@2RErBR4x)uwA5CP$)6ws7%`^4a; z9Q@MexfTn9rkrs-GmK+rE*~#k&kla6(;0USQcnyJ1FHS5Z<+|O({YS3Oz1(Em&<8#Y>3w1&ruHr6wk5FlI~BnnNk%tS{t~_&m<+ zZlJ~BQN+%`?l(I>yO|HNKa4T%&cc1hY{r-c4UwZ#A!x32ZJ1z0uI31XJR1jz3@WDi znP^x_rjKAPGs;LpVt^PR28e<6 zWWbyUR(n0mr>cnoV&De`aDNcc5FLYsMzwW7hu3HH*AY=b$F~HcFz6U8G=c|&>r_CU z%FPpl>vXUS6XzH#H0pH5)ygoBS-E_?aJ4$vg$iff(MUZpKn$!hP}4&j&;N7yWhx)} zt0^=h28e-w#sIGmy`c+5nX~mO0O_tutpET3 literal 0 HcmV?d00001 diff --git a/src/test/kotlin/com/coded/.DS_Store b/src/test/kotlin/com/coded/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..f464fe6a64e4f119a0f49a9c83ec17ea9e740025 GIT binary patch literal 6148 zcmeHK%}T>S5Z-O8O({YS3OxqA7Ob|4;w8lT0!H+pQWH{YFz%M5HHT8jSzpK}@p+ut z-5i1eZz6UEcE8#A+0A^A{b7u8Zy6mjW;4btXowt@8bNcdt6_o>xtc?;S(s<@Fp*)+ zM1RqQ-@eTM%bYTnkQg8ahyh|? z^B6E^fz{o-(y3x%fEf6J0o)%PXo#-CLZjL`pu_7k`df%7pyOKt(J|;6EHr`#gzHp5 zoyyGS5T0$T-BN@e6nYGJEm&<8#Y?F51&ruHr8cD0V9b`JwTDv3SzpK}@p+ut z-3X;QcoMNQu=~x<&u->}><<8l-Yhr-XaIo3Mkq)r5Hc6KN;a5K=s6MyA%?L(PbUQv z{Y4Xfy95OZ1Tez>`}_S!`RM!bCsCMA+wD(LDp$6)tFkKV^1*vjb8kAF&eGm6xuemw zQjwqQL;ofm%?FL$3l&d?VLVE7LKuuNU#B(I8yN#eR*CU&&Uig z1Iz$3usICaGeFiir(~{_8DIu}$N=pR4mLv9VrEcp9oW(Jnfw((64dD}LFia?EoKJM zgCa~SqDd9@i6Kln+8rC`TFeZZbP#%FoX4)5KVF1h9qo<|2jLpzo*7^URv9RpVS~>9 zOZ;UDANi{(JYoizfq%w;sPw&l4~w#A>sonq);ic8v5`<*MhXh*E0+Kq&_2@CPUCk- a$2iwwW{_qfyG}>si-0DCJ7(Y)82AE0V@(zS literal 0 HcmV?d00001 diff --git a/src/test/kotlin/com/coded/spring/ordering/.DS_Store b/src/test/kotlin/com/coded/spring/ordering/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..3b1f13167f9fd1286e7780517c53eade817a5ad0 GIT binary patch literal 6148 zcmeHK%}T>S5Z>*NO({YT3Oz1(Em&<8#Y>3w1&ruHr6we3FlI}WnnNk%tS{t~_&m<+ zZlJ~BQN+%`?l(I>yO|HNKa4T%%!32Qx{NUk8X`xfLeO04s+nL!uI5PnJe~Tn^ed+M znTG8DR5dX`4E(?V?hgVQqHVCysJ0I1@cNAY1|kaR_?AEv25p0dM(}`eoeHQ^ zxp`u6oep+k;%tM3MxD;MS{ddsE0>QKu2u)TP~nW*8mT7+h=Fwm>U!A4^Zx>VnaW50 zdJ2t*0b<~vF~A#RckDn>=4|~|9-g%V+5 literal 0 HcmV?d00001