diff --git a/.gitignore b/.gitignore
index 549e00a..f72c5bd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,33 +1,3 @@
-HELP.md
-target/
-!.mvn/wrapper/maven-wrapper.jar
-!**/src/main/**/target/
-!**/src/test/**/target/
-
-### STS ###
-.apt_generated
-.classpath
-.factorypath
-.project
-.settings
-.springBeans
-.sts4-cache
-
-### IntelliJ IDEA ###
-.idea
-*.iws
-*.iml
-*.ipr
-
-### NetBeans ###
-/nbproject/private/
-/nbbuild/
-/dist/
-/nbdist/
-/.nb-gradle/
-build/
-!**/src/main/**/build/
-!**/src/test/**/build/
-
-### VS Code ###
-.vscode/
+ordering/src/main/resources/application.properties
+authentication/src/main/resources/application.properties
+src/main/resources/application.properties
\ No newline at end of file
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..075303c
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..694ced6
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
new file mode 100644
index 0000000..b301a31
--- /dev/null
+++ b/.idea/jarRepositories.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml
new file mode 100644
index 0000000..214cb49
--- /dev/null
+++ b/.idea/kotlinc.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..a2c32e8
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/authentication/pom.xml b/authentication/pom.xml
new file mode 100644
index 0000000..ddcaf97
--- /dev/null
+++ b/authentication/pom.xml
@@ -0,0 +1,15 @@
+
+
+ 4.0.0
+
+ com.coded.spring
+ Barrak
+ 0.0.1-SNAPSHOT
+
+
+ authentication
+
+
+
\ No newline at end of file
diff --git a/src/main/kotlin/com/coded/spring/ordering/Application.kt b/authentication/src/main/kotlin/authentication/AuthenticationApplication.kt
similarity index 61%
rename from src/main/kotlin/com/coded/spring/ordering/Application.kt
rename to authentication/src/main/kotlin/authentication/AuthenticationApplication.kt
index 8554e49..eb6774c 100644
--- a/src/main/kotlin/com/coded/spring/ordering/Application.kt
+++ b/authentication/src/main/kotlin/authentication/AuthenticationApplication.kt
@@ -1,11 +1,11 @@
-package com.coded.spring.ordering
+package authentication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
@SpringBootApplication
-class Application
+class AuthenticationApplication
fun main(args: Array) {
- runApplication(*args)
-}
+ runApplication(*args)
+}
\ No newline at end of file
diff --git a/authentication/src/main/kotlin/authentication/AuthenticationController.kt b/authentication/src/main/kotlin/authentication/AuthenticationController.kt
new file mode 100644
index 0000000..84e3c7f
--- /dev/null
+++ b/authentication/src/main/kotlin/authentication/AuthenticationController.kt
@@ -0,0 +1,78 @@
+package authentication
+
+import RegistrationRequestDTO
+import authentication.jwt.JwtService
+import authentication.users.UsersService
+import io.swagger.v3.oas.annotations.tags.Tag
+import org.springframework.http.ResponseEntity
+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.*
+import java.security.Principal
+
+@Tag(name = "AuthenticationAPI")
+@RestController
+@RequestMapping("/authentication")
+class AuthController(
+ private val authenticationManager: AuthenticationManager,
+ private val userDetailsService: UserDetailsService,
+ private val jwtService: JwtService,
+ private val usersService: UsersService
+) {
+
+ // login page
+ @PostMapping("/login")
+ fun login(@RequestBody authRequest: AuthRequest): AuthResponse {
+
+ // create a spring security authentication using the username and password from the request
+ val authToken = UsernamePasswordAuthenticationToken(authRequest.username, authRequest.password)
+ // then the credentials will be authenticated by authentication manager
+ val authentication = authenticationManager.authenticate(authToken)
+
+ // check if authentication is successful
+ if (authentication.isAuthenticated) {
+
+ // load the user details from the userDetailsService
+ val userDetails = userDetailsService.loadUserByUsername(authRequest.username)
+ // Uses a JWT (JSON Web Token) service to generate a token for the authenticated user.
+ val token = jwtService.generateToken(userDetails.username)
+ // Returns a response object containing the JWT token
+ return AuthResponse(token)
+ } else {
+ throw UsernameNotFoundException("Invalid user request!")
+ }
+ }
+
+ // register
+ @PostMapping("/register")
+ fun addUser(@RequestBody request: RegistrationRequestDTO) {
+ usersService.registerUsers(request)
+ ResponseEntity.ok()
+ }
+
+
+ // check the token
+ @PostMapping("/check-token")
+ fun checkToken(
+ principal: Principal
+ ): CheckTokenResponse {
+ return CheckTokenResponse(
+ userId = usersService.findByUsername(principal.name)
+ )
+ }
+
+}
+
+data class CheckTokenResponse(
+ val userId: Long
+)
+
+data class AuthRequest(
+ val username: String,
+ val password: String
+)
+
+data class AuthResponse(
+ val token: String
+)
\ No newline at end of file
diff --git a/authentication/src/main/kotlin/authentication/CustomUserDetailsClass.kt b/authentication/src/main/kotlin/authentication/CustomUserDetailsClass.kt
new file mode 100644
index 0000000..d68bece
--- /dev/null
+++ b/authentication/src/main/kotlin/authentication/CustomUserDetailsClass.kt
@@ -0,0 +1,28 @@
+package authentication
+
+import authentication.users.UserEntity
+import authentication.users.UsersRepository
+import jakarta.inject.Named
+import org.springframework.security.core.userdetails.User
+import org.springframework.security.core.userdetails.UserDetails
+import org.springframework.security.core.userdetails.UserDetailsService
+import org.springframework.security.core.userdetails.UsernameNotFoundException
+import org.springframework.stereotype.Service
+
+
+@Service
+class CustomUserDetailsClass(
+ private val usersRepository: UsersRepository
+): UserDetailsService{
+
+ override fun loadUserByUsername(username: String): UserDetails {
+ val user: UserEntity = 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/authentication/src/main/kotlin/authentication/LoggingFilter.kt b/authentication/src/main/kotlin/authentication/LoggingFilter.kt
new file mode 100644
index 0000000..46bb417
--- /dev/null
+++ b/authentication/src/main/kotlin/authentication/LoggingFilter.kt
@@ -0,0 +1,40 @@
+package authentication
+
+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/authentication/src/main/kotlin/authentication/SecurityConfig.kt b/authentication/src/main/kotlin/authentication/SecurityConfig.kt
new file mode 100644
index 0000000..184cbb3
--- /dev/null
+++ b/authentication/src/main/kotlin/authentication/SecurityConfig.kt
@@ -0,0 +1,65 @@
+package authentication
+
+import authentication.jwt.JwtAuthFilter
+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: JwtAuthFilter,
+ private val userDetailsService: UserDetailsService
+) {
+
+ @Bean
+ fun passwordEncoder(): PasswordEncoder = BCryptPasswordEncoder()
+
+ @Bean
+ fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
+ http.csrf { it.disable() }
+ .authorizeHttpRequests {
+ it
+ .requestMatchers("/authentication/**").permitAll()
+ .requestMatchers("/authentication/login").permitAll()
+ .requestMatchers("/hello").permitAll()
+ .requestMatchers("/authentication/check-token").authenticated()
+ // swagger
+ .requestMatchers("/api-docs").permitAll()
+ // registration endpoint
+
+ // rest of endpoints will need authentication
+ .anyRequest().authenticated()
+ }
+ .sessionManagement {
+ it.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+ }
+ .authenticationProvider(authenticationProvider())
+ .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter::class.java)
+
+ return http.build();
+ }
+
+ @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/authentication/src/main/kotlin/authentication/jwt/JwtAuthFilter.kt b/authentication/src/main/kotlin/authentication/jwt/JwtAuthFilter.kt
new file mode 100644
index 0000000..407bcb9
--- /dev/null
+++ b/authentication/src/main/kotlin/authentication/jwt/JwtAuthFilter.kt
@@ -0,0 +1,45 @@
+package 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 JwtAuthFilter(
+ 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/authentication/src/main/kotlin/authentication/jwt/JwtService.kt b/authentication/src/main/kotlin/authentication/jwt/JwtService.kt
new file mode 100644
index 0000000..79d9387
--- /dev/null
+++ b/authentication/src/main/kotlin/authentication/jwt/JwtService.kt
@@ -0,0 +1,50 @@
+package authentication.jwt
+
+
+import io.jsonwebtoken.*
+import java.util.*
+import javax.crypto.SecretKey
+import io.jsonwebtoken.SignatureAlgorithm
+import io.jsonwebtoken.security.Keys
+import org.springframework.stereotype.Component
+import java.util.*
+
+
+@Component
+class JwtService {
+
+ private val secretKey: SecretKey = Keys.secretKeyFor(SignatureAlgorithm.HS256)
+ private val expirationsMs: Long = 1000 * 60 * 60
+
+ // generate token for the user
+ fun generateToken(username: String): String {
+ val now = Date()
+ val expiry = Date(now.time + expirationsMs)
+
+ return Jwts.builder()
+ .setSubject(username)
+ .setIssuedAt(now)
+ .setExpiration(expiry)
+ .signWith(secretKey)
+ .compact()
+ }
+
+ // extract username from the token itself
+ fun extractUsername(token: String): String =
+ Jwts.parserBuilder()
+ .setSigningKey(secretKey)
+ .build()
+ .parseClaimsJws(token)
+ .body
+ .subject
+
+ // check if token is valid or not
+ 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/authentication/src/main/kotlin/authentication/users/UserRepository.kt b/authentication/src/main/kotlin/authentication/users/UserRepository.kt
new file mode 100644
index 0000000..1a04034
--- /dev/null
+++ b/authentication/src/main/kotlin/authentication/users/UserRepository.kt
@@ -0,0 +1,39 @@
+package authentication.users
+
+import jakarta.inject.Named
+import jakarta.persistence.*
+import org.springframework.data.jpa.repository.JpaRepository
+
+@Named
+interface UsersRepository : JpaRepository {
+ fun age(age: Int): MutableList
+ fun findByUsername(username: String): UserEntity?
+ fun existsByUsername(username: String): Boolean
+}
+
+@Entity
+@Table(name = "users")
+data class UserEntity(
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ var id: Long? = null,
+ var name: String,
+ var age: Int,
+
+ @Column(unique = true) // make sure it's unique
+ var username: String,
+
+ var password: String,
+
+// @Enumerated(EnumType.STRING)
+// val role: Roles = Roles.USER
+
+){
+ constructor() : this(null, "", 0,"username","password")
+}
+
+enum class Roles {
+ USER, ADMIN
+}
+
+
diff --git a/authentication/src/main/kotlin/authentication/users/UsersController.kt b/authentication/src/main/kotlin/authentication/users/UsersController.kt
new file mode 100644
index 0000000..0a08332
--- /dev/null
+++ b/authentication/src/main/kotlin/authentication/users/UsersController.kt
@@ -0,0 +1,22 @@
+package authentication.users
+
+import RegistrationResponseDto
+import org.springframework.http.ResponseEntity
+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
+import io.swagger.v3.oas.annotations.tags.Tag
+
+@Tag(name = "UserAPI")
+@RestController
+class UsersController(
+ private val usersService: UsersService,
+
+){
+
+ @GetMapping("/authentication/users/list")
+ fun users() = usersService.listUsers()
+
+
+}
\ No newline at end of file
diff --git a/authentication/src/main/kotlin/authentication/users/UsersDTO.kt b/authentication/src/main/kotlin/authentication/users/UsersDTO.kt
new file mode 100644
index 0000000..8eac6a1
--- /dev/null
+++ b/authentication/src/main/kotlin/authentication/users/UsersDTO.kt
@@ -0,0 +1,14 @@
+// Change this:
+data class RegistrationRequestDTO(
+ val name: String,
+ val age: Int,
+ val username: String,
+ val password: String
+)
+// To this:
+
+
+data class RegistrationResponseDto(
+ val message: String,
+ val username: String
+)
\ No newline at end of file
diff --git a/authentication/src/main/kotlin/authentication/users/UsersService.kt b/authentication/src/main/kotlin/authentication/users/UsersService.kt
new file mode 100644
index 0000000..bf66bca
--- /dev/null
+++ b/authentication/src/main/kotlin/authentication/users/UsersService.kt
@@ -0,0 +1,77 @@
+package authentication.users
+
+import RegistrationRequestDTO
+
+import jakarta.inject.Named
+import org.springframework.security.crypto.password.PasswordEncoder
+
+@Named
+class UsersService(
+ private val usersRepository: UsersRepository,
+ private val passwordEncoder: PasswordEncoder // Added missing dependency
+) {
+
+ fun findByUsername(username: String): Long {
+ return usersRepository.findByUsername(username)?.id
+ ?: throw IllegalArgumentException("User has no id")
+ }
+
+ fun listUsers(): List = usersRepository.findAll().map {
+ User(
+ id = it.id,
+ name = it.name,
+ age = it.age,
+ )
+ }
+
+ fun registerUsers(request: RegistrationRequestDTO): UserEntity {
+
+ //check if username exists already
+ if(usersRepository.existsByUsername(request.username)){
+ throw IllegalArgumentException("user name already exists")
+ }
+
+ // Validate the password
+ val password = request.password
+
+ // check pass length
+ if (password.length < 6) {
+ throw IllegalArgumentException("Password must be at least 6 characters long")
+ }
+
+ // check if there's any uppercase letter
+ if (!password.any { it.isUpperCase() }) {
+ throw IllegalArgumentException("Password must contain at least one capital letter")
+ }
+
+ // check if there's any digits
+ if (!password.any { it.isDigit() }) {
+ throw IllegalArgumentException("Password must contain at least one number")
+ }
+
+ // create user
+ val user = UserEntity(
+ name = request.name,
+ age = request.age,
+ username = request.username,
+ password = passwordEncoder.encode(request.password)
+ )
+
+ // save the user
+ return usersRepository.save(user)
+ }
+}
+
+data class User(
+ val id: Long?,
+ val name: String,
+ val age: Int
+)
+
+data class RegistrationRequest(
+ val name: String,
+ val age: Int,
+ val username: String,
+ val password: String
+)
+
diff --git a/authentication/src/main/resources/application.properties b/authentication/src/main/resources/application.properties
new file mode 100644
index 0000000..f0889b4
--- /dev/null
+++ b/authentication/src/main/resources/application.properties
@@ -0,0 +1,10 @@
+spring.application.name=Kotlin.SpringbootV2
+
+server.port=8082
+
+spring.datasource.url=jdbc:postgresql://localhost:8080/myHelloDatabase
+spring.datasource.username=postgres
+spring.datasource.password=Barrak2000#
+spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
+
+springdoc.api-docs.path=/api-docs
diff --git a/authentication/target/classes/META-INF/authentication.kotlin_module b/authentication/target/classes/META-INF/authentication.kotlin_module
new file mode 100644
index 0000000..e0ddbc8
Binary files /dev/null and b/authentication/target/classes/META-INF/authentication.kotlin_module differ
diff --git a/authentication/target/classes/RegistrationRequestDTO.class b/authentication/target/classes/RegistrationRequestDTO.class
new file mode 100644
index 0000000..1f2dc52
Binary files /dev/null and b/authentication/target/classes/RegistrationRequestDTO.class differ
diff --git a/authentication/target/classes/RegistrationResponseDto.class b/authentication/target/classes/RegistrationResponseDto.class
new file mode 100644
index 0000000..06740b4
Binary files /dev/null and b/authentication/target/classes/RegistrationResponseDto.class differ
diff --git a/authentication/target/classes/application.properties b/authentication/target/classes/application.properties
new file mode 100644
index 0000000..f0889b4
--- /dev/null
+++ b/authentication/target/classes/application.properties
@@ -0,0 +1,10 @@
+spring.application.name=Kotlin.SpringbootV2
+
+server.port=8082
+
+spring.datasource.url=jdbc:postgresql://localhost:8080/myHelloDatabase
+spring.datasource.username=postgres
+spring.datasource.password=Barrak2000#
+spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
+
+springdoc.api-docs.path=/api-docs
diff --git a/authentication/target/classes/authentication/AuthController.class b/authentication/target/classes/authentication/AuthController.class
new file mode 100644
index 0000000..d688181
Binary files /dev/null and b/authentication/target/classes/authentication/AuthController.class differ
diff --git a/authentication/target/classes/authentication/AuthRequest.class b/authentication/target/classes/authentication/AuthRequest.class
new file mode 100644
index 0000000..0c1bc87
Binary files /dev/null and b/authentication/target/classes/authentication/AuthRequest.class differ
diff --git a/authentication/target/classes/authentication/AuthResponse.class b/authentication/target/classes/authentication/AuthResponse.class
new file mode 100644
index 0000000..d04e23a
Binary files /dev/null and b/authentication/target/classes/authentication/AuthResponse.class differ
diff --git a/authentication/target/classes/authentication/AuthenticationApplication.class b/authentication/target/classes/authentication/AuthenticationApplication.class
new file mode 100644
index 0000000..e0c3943
Binary files /dev/null and b/authentication/target/classes/authentication/AuthenticationApplication.class differ
diff --git a/authentication/target/classes/authentication/AuthenticationApplicationKt.class b/authentication/target/classes/authentication/AuthenticationApplicationKt.class
new file mode 100644
index 0000000..4bb8e7a
Binary files /dev/null and b/authentication/target/classes/authentication/AuthenticationApplicationKt.class differ
diff --git a/authentication/target/classes/authentication/CheckTokenResponse.class b/authentication/target/classes/authentication/CheckTokenResponse.class
new file mode 100644
index 0000000..977f339
Binary files /dev/null and b/authentication/target/classes/authentication/CheckTokenResponse.class differ
diff --git a/authentication/target/classes/authentication/CustomUserDetailsClass.class b/authentication/target/classes/authentication/CustomUserDetailsClass.class
new file mode 100644
index 0000000..8f84841
Binary files /dev/null and b/authentication/target/classes/authentication/CustomUserDetailsClass.class differ
diff --git a/authentication/target/classes/authentication/LoggingFilter.class b/authentication/target/classes/authentication/LoggingFilter.class
new file mode 100644
index 0000000..1f26aa4
Binary files /dev/null and b/authentication/target/classes/authentication/LoggingFilter.class differ
diff --git a/authentication/target/classes/authentication/SecurityConfig.class b/authentication/target/classes/authentication/SecurityConfig.class
new file mode 100644
index 0000000..3d0bec9
Binary files /dev/null and b/authentication/target/classes/authentication/SecurityConfig.class differ
diff --git a/authentication/target/classes/authentication/jwt/JwtAuthFilter.class b/authentication/target/classes/authentication/jwt/JwtAuthFilter.class
new file mode 100644
index 0000000..3a523cf
Binary files /dev/null and b/authentication/target/classes/authentication/jwt/JwtAuthFilter.class differ
diff --git a/authentication/target/classes/authentication/jwt/JwtService.class b/authentication/target/classes/authentication/jwt/JwtService.class
new file mode 100644
index 0000000..271b692
Binary files /dev/null and b/authentication/target/classes/authentication/jwt/JwtService.class differ
diff --git a/authentication/target/classes/authentication/users/RegistrationRequest.class b/authentication/target/classes/authentication/users/RegistrationRequest.class
new file mode 100644
index 0000000..0f86da1
Binary files /dev/null and b/authentication/target/classes/authentication/users/RegistrationRequest.class differ
diff --git a/authentication/target/classes/authentication/users/Roles.class b/authentication/target/classes/authentication/users/Roles.class
new file mode 100644
index 0000000..f6d5609
Binary files /dev/null and b/authentication/target/classes/authentication/users/Roles.class differ
diff --git a/authentication/target/classes/authentication/users/User.class b/authentication/target/classes/authentication/users/User.class
new file mode 100644
index 0000000..0bd0301
Binary files /dev/null and b/authentication/target/classes/authentication/users/User.class differ
diff --git a/authentication/target/classes/authentication/users/UserEntity.class b/authentication/target/classes/authentication/users/UserEntity.class
new file mode 100644
index 0000000..f6dbfd1
Binary files /dev/null and b/authentication/target/classes/authentication/users/UserEntity.class differ
diff --git a/authentication/target/classes/authentication/users/UsersController.class b/authentication/target/classes/authentication/users/UsersController.class
new file mode 100644
index 0000000..ff8c1b7
Binary files /dev/null and b/authentication/target/classes/authentication/users/UsersController.class differ
diff --git a/authentication/target/classes/authentication/users/UsersRepository.class b/authentication/target/classes/authentication/users/UsersRepository.class
new file mode 100644
index 0000000..d3917d0
Binary files /dev/null and b/authentication/target/classes/authentication/users/UsersRepository.class differ
diff --git a/authentication/target/classes/authentication/users/UsersService.class b/authentication/target/classes/authentication/users/UsersService.class
new file mode 100644
index 0000000..e16cb77
Binary files /dev/null and b/authentication/target/classes/authentication/users/UsersService.class differ
diff --git a/ordering/pom.xml b/ordering/pom.xml
new file mode 100644
index 0000000..0cfd102
--- /dev/null
+++ b/ordering/pom.xml
@@ -0,0 +1,22 @@
+
+
+ 4.0.0
+
+ com.coded.spring
+ Barrak
+ 0.0.1-SNAPSHOT
+
+
+ ordering
+
+
+ com.coded.spring
+ authentication
+ 0.0.1-SNAPSHOT
+ compile
+
+
+
+
\ No newline at end of file
diff --git a/ordering/src/main/kotlin/LoggingFilter.kt b/ordering/src/main/kotlin/LoggingFilter.kt
new file mode 100644
index 0000000..1dfcaed
--- /dev/null
+++ b/ordering/src/main/kotlin/LoggingFilter.kt
@@ -0,0 +1,40 @@
+package 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/ordering/src/main/kotlin/OrderingApplication.kt b/ordering/src/main/kotlin/OrderingApplication.kt
new file mode 100644
index 0000000..a1fc64b
--- /dev/null
+++ b/ordering/src/main/kotlin/OrderingApplication.kt
@@ -0,0 +1,17 @@
+package 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
+
+@SpringBootApplication
+class OrderingApplication
+
+fun main(args: Array) {
+ runApplication(*args)
+}
+
+val orderingCacheConfig = Config("hello-world-cache")
+val serverCache: HazelcastInstance = Hazelcast.newHazelcastInstance(orderingCacheConfig)
\ No newline at end of file
diff --git a/ordering/src/main/kotlin/client/AuthenticationClient.kt b/ordering/src/main/kotlin/client/AuthenticationClient.kt
new file mode 100644
index 0000000..ad85bf5
--- /dev/null
+++ b/ordering/src/main/kotlin/client/AuthenticationClient.kt
@@ -0,0 +1,33 @@
+package ordering.client
+
+import authentication.CheckTokenResponse
+import jakarta.inject.Named
+import org.springframework.core.ParameterizedTypeReference
+import org.springframework.http.*
+import org.springframework.web.client.RestTemplate
+import org.springframework.web.client.exchange
+
+@Named
+class AuthenticationClient {
+
+ fun checkToken(token: String): CheckTokenResponse {
+ val restTemplate = RestTemplate()
+ val url = "http://localhost:8082/authentication/check-token"
+
+ // Create headers with token
+ val headers = HttpHeaders()
+ headers.set("Authorization", "Bearer $token")
+
+ // Create request entity with headers
+ val requestEntity = HttpEntity(headers)
+
+ val response = restTemplate.exchange(
+ url = url,
+ method = HttpMethod.POST,
+ requestEntity = requestEntity,
+ object : ParameterizedTypeReference() {}
+ )
+ return response.body ?: throw IllegalStateException("Check token response has no body ...")
+ }
+
+}
\ No newline at end of file
diff --git a/ordering/src/main/kotlin/items/ItemsController.kt b/ordering/src/main/kotlin/items/ItemsController.kt
new file mode 100644
index 0000000..8def5d4
--- /dev/null
+++ b/ordering/src/main/kotlin/items/ItemsController.kt
@@ -0,0 +1,22 @@
+//package items
+//
+//import io.swagger.v3.oas.annotations.tags.Tag
+//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
+//
+//@Tag(name = "ItemAPI")
+//@RestController
+//class ItemsController(
+// private val itemsService: ItemsService
+//) {
+//
+// @GetMapping("/items/list")
+// fun items() = itemsService.listItems()
+//
+// @PostMapping("/items/create")
+// fun addItems(@RequestBody request: CreateItemRequestDTO): ItemDTO {
+// return itemsService.createItem(request)
+// }
+//}
\ No newline at end of file
diff --git a/ordering/src/main/kotlin/items/ItemsDTO.kt b/ordering/src/main/kotlin/items/ItemsDTO.kt
new file mode 100644
index 0000000..15a99ff
--- /dev/null
+++ b/ordering/src/main/kotlin/items/ItemsDTO.kt
@@ -0,0 +1,17 @@
+package ordering.items
+
+data class CreateItemRequestDTO(
+
+ var name: String,
+ var quantity: Int,
+ var order_id: Long
+)
+
+data class ItemDTO(
+ val name: String,
+ val quantity: Int,
+)
+
+data class ItemsListDTO(
+ val items: List
+)
\ No newline at end of file
diff --git a/ordering/src/main/kotlin/items/ItemsRepository.kt b/ordering/src/main/kotlin/items/ItemsRepository.kt
new file mode 100644
index 0000000..6865742
--- /dev/null
+++ b/ordering/src/main/kotlin/items/ItemsRepository.kt
@@ -0,0 +1,27 @@
+package ordering.items
+
+import jakarta.inject.Named
+import jakarta.persistence.*
+import org.springframework.data.jpa.repository.JpaRepository
+
+@Named
+interface ItemsRepository: JpaRepository
+
+@Entity
+@Table(name = "items")
+data class ItemEntity(
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ var id: Long? = null,
+ var name: String,
+ var quantity: Int,
+
+ @Column(name = "order_id")
+ var orderId: Long,
+
+// @Column("'name'")
+
+
+){
+ constructor(): this(null, "", 0, 0)
+}
\ No newline at end of file
diff --git a/ordering/src/main/kotlin/items/ItemsService.kt b/ordering/src/main/kotlin/items/ItemsService.kt
new file mode 100644
index 0000000..a9821fb
--- /dev/null
+++ b/ordering/src/main/kotlin/items/ItemsService.kt
@@ -0,0 +1,44 @@
+//package items
+//
+//import orders.OrderRepository
+//import jakarta.inject.Named
+//
+//@Named
+//class ItemsService(
+// private val itemsRepository: ItemsRepository,
+// private val orderRepository: OrderRepository // Added to fetch orders
+//
+//) {
+//
+// fun listItems(): List = itemsRepository.findAll().map {
+// ItemDTO(
+// id = it.id,
+// name = it.name,
+// quantity = it.quantity,
+// orderId = it.order.id
+// )
+//
+// }
+//
+// fun createItem(request: CreateItemRequestDTO): ItemDTO {
+// val order = orderRepository.findById(request.order_id)
+// .orElseThrow { IllegalArgumentException("Order not found with id: ${request.order_id}") }
+//
+// val item = ItemEntity(
+// name = request.name,
+// quantity = request.quantity,
+// order = order
+// )
+//
+// val savedItem = itemsRepository.save(item)
+//
+// return ItemDTO(
+// id = savedItem.id,
+// name = savedItem.name,
+// quantity = savedItem.quantity,
+// orderId = savedItem.order.id
+// )
+// }
+//
+//
+//}
\ No newline at end of file
diff --git a/ordering/src/main/kotlin/orders/OrderController.kt b/ordering/src/main/kotlin/orders/OrderController.kt
new file mode 100644
index 0000000..27d4190
--- /dev/null
+++ b/ordering/src/main/kotlin/orders/OrderController.kt
@@ -0,0 +1,45 @@
+package ordering.orders
+
+import authentication.users.UsersService
+import io.swagger.v3.oas.annotations.tags.Tag
+import jakarta.servlet.http.HttpServletRequest
+import ordering.items.ItemDTO
+
+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
+
+//@Tag(name = "OrderAPI")
+@RestController
+class OrderController(
+ private val orderService: OrderService,
+
+) {
+
+ @GetMapping("/orders/orders")
+ fun orders(): OrdersListDTO {
+ val ordersList = orderService.listOrders()
+ return OrdersListDTO(orders = ordersList)
+ }
+
+ // create order
+ @PostMapping("/orders/orders")
+ fun createOrder(
+ request: HttpServletRequest,
+ @RequestBody body: CreateOrderRequest
+ ): CreateOrderResponse {
+ val userId = request.getAttribute("userId") as Long
+ val order = orderService.createOrder(userId, body.items)
+ return CreateOrderResponse(
+ order.id,
+ order.items
+ )
+ }
+
+}
+
+data class CreateOrderResponse(
+ val id: Long?,
+ val items: List?
+)
diff --git a/ordering/src/main/kotlin/orders/OrderRepository.kt b/ordering/src/main/kotlin/orders/OrderRepository.kt
new file mode 100644
index 0000000..b1a925c
--- /dev/null
+++ b/ordering/src/main/kotlin/orders/OrderRepository.kt
@@ -0,0 +1,32 @@
+package ordering.orders
+
+
+import jakarta.inject.Named
+import jakarta.persistence.*
+import ordering.items.ItemEntity
+import org.springframework.data.jpa.repository.JpaRepository
+
+@Named
+interface OrderRepository : JpaRepository {
+ fun findByUserId(userId: Long): List
+}
+
+@Entity
+@Table(name = "orders")
+data class OrderEntity(
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ val id: Long? = null,
+
+ @Column(name = "user_id")
+ val userId: Long,
+
+ // join
+ @OneToMany
+ val items: List? = null
+
+
+){
+ constructor(): this(null, 0, listOf())
+
+}
\ No newline at end of file
diff --git a/ordering/src/main/kotlin/orders/OrderService.kt b/ordering/src/main/kotlin/orders/OrderService.kt
new file mode 100644
index 0000000..03a6c07
--- /dev/null
+++ b/ordering/src/main/kotlin/orders/OrderService.kt
@@ -0,0 +1,50 @@
+package ordering.orders
+
+import authentication.users.UsersRepository
+
+import jakarta.inject.Named
+import ordering.items.ItemDTO
+import ordering.items.ItemEntity
+import ordering.items.ItemsRepository
+
+@Named
+class OrderService(
+ private val orderRepository: OrderRepository,
+ private val itemsRepository: ItemsRepository
+) {
+
+ // listing orders
+ fun listOrders(): List = orderRepository.findAll().map { order ->
+ OrderDTO(
+ id = order.id, //transfer the orderId to dto
+ items = order.items?.map { item ->
+ //for each item in the order, create an ItemDTO
+ ItemDTO(
+ name = item.name,
+ quantity = item.quantity
+ )
+ }
+ )
+ }
+
+ // creating new order
+ fun createOrder(userId: Long, items: List): OrderDTO {
+ val newOrder = OrderEntity(userId = userId)
+ val savedOrder = orderRepository.save(newOrder)
+
+ val newItems = items.map {
+ ItemEntity(
+ name = it.name,
+ quantity = it.quantity,
+ orderId = savedOrder.id!!
+ )
+ }
+ itemsRepository.saveAll(newItems)
+
+ return OrderDTO(
+ id = savedOrder.id,
+ items = newItems.map { ItemDTO(it.name, it.quantity) }
+ )
+ }
+}
+
diff --git a/ordering/src/main/kotlin/orders/OrdersDTO.kt b/ordering/src/main/kotlin/orders/OrdersDTO.kt
new file mode 100644
index 0000000..5cd6086
--- /dev/null
+++ b/ordering/src/main/kotlin/orders/OrdersDTO.kt
@@ -0,0 +1,17 @@
+package ordering.orders
+
+import ordering.items.ItemDTO
+
+// return this when user asking for order list
+data class OrderDTO(
+ val id: Long?,
+ val items: List?
+)
+
+data class OrdersListDTO(
+ val orders: List
+)
+
+data class CreateOrderRequest(
+ val items: List
+)
\ No newline at end of file
diff --git a/ordering/src/main/kotlin/security/RemoteAuthenticationFilter.kt b/ordering/src/main/kotlin/security/RemoteAuthenticationFilter.kt
new file mode 100644
index 0000000..bd700b2
--- /dev/null
+++ b/ordering/src/main/kotlin/security/RemoteAuthenticationFilter.kt
@@ -0,0 +1,32 @@
+package ordering.security
+
+import jakarta.servlet.FilterChain
+import jakarta.servlet.http.*
+import ordering.client.AuthenticationClient
+import org.springframework.stereotype.Component
+import org.springframework.web.filter.OncePerRequestFilter
+
+@Component
+class RemoteAuthenticationFilter(
+ private val authenticationClient: AuthenticationClient,
+) : OncePerRequestFilter() {
+
+ override fun doFilterInternal(
+ request: HttpServletRequest,
+ response: HttpServletResponse,
+ filterChain: FilterChain
+ ) {
+ logger.info("Remote authentication filter running...")
+ val authHeader = request.getHeader("Authorization")
+ if (authHeader == null || !authHeader.startsWith("Bearer ")) {
+ filterChain.doFilter(request, response)
+ return
+ }
+
+ val token = authHeader.substring(7)
+ val result = authenticationClient.checkToken(token)
+ request.setAttribute("userId", result.userId)
+
+ filterChain.doFilter(request, response)
+ }
+}
\ No newline at end of file
diff --git a/ordering/src/main/kotlin/security/SecurityConfig.kt b/ordering/src/main/kotlin/security/SecurityConfig.kt
new file mode 100644
index 0000000..5586252
--- /dev/null
+++ b/ordering/src/main/kotlin/security/SecurityConfig.kt
@@ -0,0 +1,30 @@
+package ordering.security
+
+import org.springframework.context.annotation.Bean
+import org.springframework.context.annotation.Configuration
+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.web.SecurityFilterChain
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
+
+@Configuration
+@EnableWebSecurity
+class SecurityConfig(
+ private val remoteAuthFilter: RemoteAuthenticationFilter
+) {
+
+ @Bean
+ fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
+ http.csrf { it.disable() }
+ .authorizeHttpRequests {
+ it.anyRequest().permitAll()
+ }
+ .sessionManagement {
+ it.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+ }
+ .addFilterBefore(remoteAuthFilter, UsernamePasswordAuthenticationFilter::class.java)
+
+ return http.build()
+ }
+}
\ No newline at end of file
diff --git a/ordering/src/main/resources/application.properties b/ordering/src/main/resources/application.properties
new file mode 100644
index 0000000..2bf2893
--- /dev/null
+++ b/ordering/src/main/resources/application.properties
@@ -0,0 +1,10 @@
+spring.application.name=Kotlin.SpringbootV2
+
+server.port=8083
+
+spring.datasource.url=jdbc:postgresql://localhost:8080/myHelloDatabase
+spring.datasource.username=postgres
+spring.datasource.password=Barrak2000#
+spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
+
+springdoc.api-docs.path=/api-docs
diff --git a/ordering/target/classes/META-INF/ordering.kotlin_module b/ordering/target/classes/META-INF/ordering.kotlin_module
new file mode 100644
index 0000000..5d4bb7c
Binary files /dev/null and b/ordering/target/classes/META-INF/ordering.kotlin_module differ
diff --git a/ordering/target/classes/application.properties b/ordering/target/classes/application.properties
new file mode 100644
index 0000000..2bf2893
--- /dev/null
+++ b/ordering/target/classes/application.properties
@@ -0,0 +1,10 @@
+spring.application.name=Kotlin.SpringbootV2
+
+server.port=8083
+
+spring.datasource.url=jdbc:postgresql://localhost:8080/myHelloDatabase
+spring.datasource.username=postgres
+spring.datasource.password=Barrak2000#
+spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
+
+springdoc.api-docs.path=/api-docs
diff --git a/ordering/target/classes/ordering/LoggingFilter.class b/ordering/target/classes/ordering/LoggingFilter.class
new file mode 100644
index 0000000..0ea4566
Binary files /dev/null and b/ordering/target/classes/ordering/LoggingFilter.class differ
diff --git a/ordering/target/classes/ordering/OrderingApplication.class b/ordering/target/classes/ordering/OrderingApplication.class
new file mode 100644
index 0000000..ff9a185
Binary files /dev/null and b/ordering/target/classes/ordering/OrderingApplication.class differ
diff --git a/ordering/target/classes/ordering/OrderingApplicationKt.class b/ordering/target/classes/ordering/OrderingApplicationKt.class
new file mode 100644
index 0000000..fee0751
Binary files /dev/null and b/ordering/target/classes/ordering/OrderingApplicationKt.class differ
diff --git a/ordering/target/classes/ordering/client/AuthenticationClient$checkToken$$inlined$exchange$1.class b/ordering/target/classes/ordering/client/AuthenticationClient$checkToken$$inlined$exchange$1.class
new file mode 100644
index 0000000..9bcc38a
Binary files /dev/null and b/ordering/target/classes/ordering/client/AuthenticationClient$checkToken$$inlined$exchange$1.class differ
diff --git a/ordering/target/classes/ordering/client/AuthenticationClient$checkToken$response$1.class b/ordering/target/classes/ordering/client/AuthenticationClient$checkToken$response$1.class
new file mode 100644
index 0000000..21161ce
Binary files /dev/null and b/ordering/target/classes/ordering/client/AuthenticationClient$checkToken$response$1.class differ
diff --git a/ordering/target/classes/ordering/client/AuthenticationClient.class b/ordering/target/classes/ordering/client/AuthenticationClient.class
new file mode 100644
index 0000000..9567369
Binary files /dev/null and b/ordering/target/classes/ordering/client/AuthenticationClient.class differ
diff --git a/ordering/target/classes/ordering/items/CreateItemRequestDTO.class b/ordering/target/classes/ordering/items/CreateItemRequestDTO.class
new file mode 100644
index 0000000..f27631c
Binary files /dev/null and b/ordering/target/classes/ordering/items/CreateItemRequestDTO.class differ
diff --git a/ordering/target/classes/ordering/items/ItemDTO.class b/ordering/target/classes/ordering/items/ItemDTO.class
new file mode 100644
index 0000000..9578e32
Binary files /dev/null and b/ordering/target/classes/ordering/items/ItemDTO.class differ
diff --git a/ordering/target/classes/ordering/items/ItemEntity.class b/ordering/target/classes/ordering/items/ItemEntity.class
new file mode 100644
index 0000000..a9897c7
Binary files /dev/null and b/ordering/target/classes/ordering/items/ItemEntity.class differ
diff --git a/ordering/target/classes/ordering/items/ItemsListDTO.class b/ordering/target/classes/ordering/items/ItemsListDTO.class
new file mode 100644
index 0000000..9220d6d
Binary files /dev/null and b/ordering/target/classes/ordering/items/ItemsListDTO.class differ
diff --git a/ordering/target/classes/ordering/items/ItemsRepository.class b/ordering/target/classes/ordering/items/ItemsRepository.class
new file mode 100644
index 0000000..e073984
Binary files /dev/null and b/ordering/target/classes/ordering/items/ItemsRepository.class differ
diff --git a/ordering/target/classes/ordering/orders/CreateOrderRequest.class b/ordering/target/classes/ordering/orders/CreateOrderRequest.class
new file mode 100644
index 0000000..cd22645
Binary files /dev/null and b/ordering/target/classes/ordering/orders/CreateOrderRequest.class differ
diff --git a/ordering/target/classes/ordering/orders/CreateOrderResponse.class b/ordering/target/classes/ordering/orders/CreateOrderResponse.class
new file mode 100644
index 0000000..16fd8e2
Binary files /dev/null and b/ordering/target/classes/ordering/orders/CreateOrderResponse.class differ
diff --git a/ordering/target/classes/ordering/orders/OrderController.class b/ordering/target/classes/ordering/orders/OrderController.class
new file mode 100644
index 0000000..c922adf
Binary files /dev/null and b/ordering/target/classes/ordering/orders/OrderController.class differ
diff --git a/ordering/target/classes/ordering/orders/OrderDTO.class b/ordering/target/classes/ordering/orders/OrderDTO.class
new file mode 100644
index 0000000..c6e17cd
Binary files /dev/null and b/ordering/target/classes/ordering/orders/OrderDTO.class differ
diff --git a/ordering/target/classes/ordering/orders/OrderEntity.class b/ordering/target/classes/ordering/orders/OrderEntity.class
new file mode 100644
index 0000000..63393e1
Binary files /dev/null and b/ordering/target/classes/ordering/orders/OrderEntity.class differ
diff --git a/ordering/target/classes/ordering/orders/OrderRepository.class b/ordering/target/classes/ordering/orders/OrderRepository.class
new file mode 100644
index 0000000..8a217d0
Binary files /dev/null and b/ordering/target/classes/ordering/orders/OrderRepository.class differ
diff --git a/ordering/target/classes/ordering/orders/OrderService.class b/ordering/target/classes/ordering/orders/OrderService.class
new file mode 100644
index 0000000..124c693
Binary files /dev/null and b/ordering/target/classes/ordering/orders/OrderService.class differ
diff --git a/ordering/target/classes/ordering/orders/OrdersListDTO.class b/ordering/target/classes/ordering/orders/OrdersListDTO.class
new file mode 100644
index 0000000..b61b493
Binary files /dev/null and b/ordering/target/classes/ordering/orders/OrdersListDTO.class differ
diff --git a/ordering/target/classes/ordering/security/RemoteAuthenticationFilter.class b/ordering/target/classes/ordering/security/RemoteAuthenticationFilter.class
new file mode 100644
index 0000000..f203fad
Binary files /dev/null and b/ordering/target/classes/ordering/security/RemoteAuthenticationFilter.class differ
diff --git a/ordering/target/classes/ordering/security/SecurityConfig.class b/ordering/target/classes/ordering/security/SecurityConfig.class
new file mode 100644
index 0000000..eeb61af
Binary files /dev/null and b/ordering/target/classes/ordering/security/SecurityConfig.class differ
diff --git a/pom.xml b/pom.xml
index 163ad53..5875045 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,9 +8,11 @@
3.4.4
+
com.coded.spring
- Ordering
+ Barrak
0.0.1-SNAPSHOT
+ pom
Kotlin.SpringbootV2
Kotlin.SpringbootV2
@@ -20,6 +22,10 @@
+
+ authentication
+ ordering
+
@@ -43,21 +49,80 @@
org.jetbrains.kotlin
kotlin-reflect
+
+ io.jsonwebtoken
+ jjwt-api
+ 0.11.5
+
+
+ io.jsonwebtoken
+ jjwt-impl
+ runtime
+ 0.11.5
+
+
+ io.jsonwebtoken
+ jjwt-jackson
+ runtime
+ 0.11.5
+
org.jetbrains.kotlin
kotlin-stdlib
-
+
+ org.springdoc
+ springdoc-openapi-starter-webmvc-api
+ 2.6.0
+
+
+ org.postgresql
+ postgresql
+ compile
+
+
+ com.hazelcast
+ hazelcast
+ 5.3.8
+
org.springframework.boot
spring-boot-starter-test
test
+
+ com.h2database
+ h2
+ test
+
org.jetbrains.kotlin
kotlin-test-junit5
test
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+
+
+
+
+
+
+
+ jakarta.inject
+ jakarta.inject-api
+ 2.0.1
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+
@@ -90,4 +155,4 @@
-
+
\ No newline at end of file
diff --git a/src/main/kotlin/com/coded/spring - Shortcut.lnk b/src/main/kotlin/com/coded/spring - Shortcut.lnk
new file mode 100644
index 0000000..f6e78c9
Binary files /dev/null and b/src/main/kotlin/com/coded/spring - Shortcut.lnk differ
diff --git a/src/main/kotlin/com/coded/spring/orders/Application.kt b/src/main/kotlin/com/coded/spring/orders/Application.kt
new file mode 100644
index 0000000..08a9aa1
--- /dev/null
+++ b/src/main/kotlin/com/coded/spring/orders/Application.kt
@@ -0,0 +1,18 @@
+package com.coded.spring.ordering
+
+import org.springframework.boot.autoconfigure.SpringBootApplication
+import org.springframework.boot.runApplication
+import com.hazelcast.config.Config;
+import com.hazelcast.core.Hazelcast
+import com.hazelcast.core.HazelcastInstance
+
+
+@SpringBootApplication
+class Application
+
+fun main(args: Array) {
+ runApplication(*args)
+}
+
+val orderingConfig = Config("Ordering-config")
+val serverCache: HazelcastInstance = Hazelcast.newHazelcastInstance(orderingConfig)
\ No newline at end of file
diff --git a/src/main/kotlin/com/coded/spring/orders/HelloWorldController.kt b/src/main/kotlin/com/coded/spring/orders/HelloWorldController.kt
new file mode 100644
index 0000000..e0ce963
--- /dev/null
+++ b/src/main/kotlin/com/coded/spring/orders/HelloWorldController.kt
@@ -0,0 +1,86 @@
+package com.coded.spring.ordering
+
+
+import com.coded.spring.ordering.orders.OrderEntity
+import com.coded.spring.ordering.orders.OrderRepository
+import com.coded.spring.ordering.users.UserEntity
+import com.coded.spring.ordering.users.UsersRepository
+import org.springframework.beans.factory.annotation.Value
+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,
+ val orderRepository: OrderRepository,
+
+ // welcome endpoint
+ @Value("\${server-welcome-message:test}")
+ val welcomeMessage: String,
+ //the feature
+ @Value("\${feature.festive.enabled:false}")
+ val festiveStatus: Boolean,
+
+ @Value("\${festive-welcome-message: Eidkom Mubarak}")
+ private val festiveWelcomeMessage: String
+){
+
+ @GetMapping("/hello")
+
+ fun helloWorld() = if(festiveStatus){
+ festiveWelcomeMessage
+ }else {
+ "$welcomeMessage Barrak"
+ }
+
+
+ @GetMapping("/cart")
+ fun cart() = "Your cart"
+
+ @GetMapping("/restaurants")
+ fun resturant() = "List of resturants"
+
+ @GetMapping("/Settings")
+ fun settings() = "Settings!"
+
+ // Post
+// @PostMapping("/my-name")
+// fun sayMyName( @RequestBody request: SayMyNameRequest) = usersRepository.save(UserEntity(name = request.name, age = request.age))
+
+ @GetMapping("/my-name")
+ fun getName(): MutableList {
+ return usersRepository.findAll()
+ }
+
+// @PostMapping("/orders")
+// fun orders( @RequestBody request: OrderRequest): OrderEntity {
+// val order = (OrderEntity(null,user))
+// return orderRepository.save(order)
+// }
+
+ @GetMapping("/orders")
+ fun getOrders(): MutableList{
+ return orderRepository.findAll()
+ }
+
+
+
+
+
+}
+
+data class SayMyNameRequest(
+ val name: String,
+ val age: Int
+)
+
+data class OrderRequest(
+ val user_id: Int,
+
+
+)
+
+
+
diff --git a/src/main/kotlin/com/coded/spring/orders/files/Barrak-online-ordering-api-swagger-01.json b/src/main/kotlin/com/coded/spring/orders/files/Barrak-online-ordering-api-swagger-01.json
new file mode 100644
index 0000000..195bf86
--- /dev/null
+++ b/src/main/kotlin/com/coded/spring/orders/files/Barrak-online-ordering-api-swagger-01.json
@@ -0,0 +1 @@
+{"openapi":"3.0.1","info":{"title":"OpenAPI definition","version":"v0"},"servers":[{"url":"http://localhost:8081","description":"Generated server url"}],"paths":{"/register":{"post":{"tags":["UserAPI"],"operationId":"registerUser","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegistrationRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/profile":{"post":{"tags":["ProfileAPI"],"operationId":"createOrUpdateProfile","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfileRequestDto"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"object"}}}}}}},"/orders/orders":{"get":{"tags":["OrderAPI"],"operationId":"orders","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/OrderDTO"}}}}}}},"post":{"tags":["OrderAPI"],"operationId":"createOrders","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOrderRequest"}}},"required":true},"responses":{"200":{"description":"OK"}}}},"/items/create":{"post":{"tags":["ItemAPI"],"operationId":"addItems","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateItemRequestDTO"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ItemDTO"}}}}}}},"/authentication/login":{"post":{"tags":["AuthenticationAPI"],"operationId":"login","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/AuthResponse"}}}}}}},"/users/list":{"get":{"tags":["UserAPI"],"operationId":"users","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/User"}}}}}}}},"/restaurants":{"get":{"tags":["hello-world-controller"],"operationId":"resturant","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"string"}}}}}}},"/orders":{"get":{"tags":["hello-world-controller"],"operationId":"getOrders","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/OrderEntity"}}}}}}}},"/my-name":{"get":{"tags":["hello-world-controller"],"operationId":"getName","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UserEntity"}}}}}}}},"/menu":{"get":{"tags":["MenuAPI"],"operationId":"menu","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MenuEntity"}}}}}}}},"/items/list":{"get":{"tags":["ItemAPI"],"operationId":"items","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Unit"}}}}}}}},"/hello":{"get":{"tags":["hello-world-controller"],"operationId":"helloWorld","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"string"}}}}}}},"/cart":{"get":{"tags":["hello-world-controller"],"operationId":"cart","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"string"}}}}}}},"/Settings":{"get":{"tags":["hello-world-controller"],"operationId":"settings","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"type":"string"}}}}}}}},"components":{"schemas":{"RegistrationRequest":{"required":["age","name","password","username"],"type":"object","properties":{"name":{"type":"string"},"age":{"type":"integer","format":"int32"},"username":{"type":"string"},"password":{"type":"string"}}},"ProfileRequestDto":{"required":["firstName","lastName","phoneNumber"],"type":"object","properties":{"firstName":{"type":"string"},"lastName":{"type":"string"},"phoneNumber":{"type":"string"}}},"CreateOrderRequest":{"required":["userId"],"type":"object","properties":{"userId":{"type":"integer","format":"int64"}}},"CreateItemRequestDTO":{"required":["name","order_id","quantity"],"type":"object","properties":{"name":{"type":"string"},"quantity":{"type":"integer","format":"int32"},"order_id":{"type":"integer","format":"int64"}}},"ItemDTO":{"required":["name","quantity"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"quantity":{"type":"integer","format":"int32"},"orderId":{"type":"integer","format":"int64"}}},"AuthRequest":{"required":["password","username"],"type":"object","properties":{"username":{"type":"string"},"password":{"type":"string"}}},"AuthResponse":{"required":["token"],"type":"object","properties":{"token":{"type":"string"}}},"User":{"required":["age","name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"age":{"type":"integer","format":"int32"}}},"ItemEntity":{"required":["name","order","quantity"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"quantity":{"type":"integer","format":"int32"},"order":{"$ref":"#/components/schemas/OrderEntity"}}},"OrderEntity":{"required":["user"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"user":{"$ref":"#/components/schemas/UserEntity"},"items":{"type":"array","items":{"$ref":"#/components/schemas/ItemEntity"}}}},"UserEntity":{"required":["age","name","password","username"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"age":{"type":"integer","format":"int32"},"username":{"type":"string"},"password":{"type":"string"}}},"OrderDTO":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"userId":{"type":"integer","format":"int64"},"items":{"type":"array","items":{"$ref":"#/components/schemas/ItemDTO"}}}},"MenuEntity":{"required":["description","name","price"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"price":{"type":"number"},"description":{"type":"string"}}},"Unit":{"type":"object"}}}}
\ No newline at end of file
diff --git a/src/main/kotlin/com/coded/spring/orders/menu/MenuController.kt b/src/main/kotlin/com/coded/spring/orders/menu/MenuController.kt
new file mode 100644
index 0000000..66044f1
--- /dev/null
+++ b/src/main/kotlin/com/coded/spring/orders/menu/MenuController.kt
@@ -0,0 +1,15 @@
+package com.coded.spring.ordering.menu
+
+import io.swagger.v3.oas.annotations.tags.Tag
+import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.RestController
+
+@Tag(name = "MenuAPI")
+@RestController
+class MenuController(
+ private val menuService: MenuService
+){
+
+ @GetMapping("menu")
+ fun menu() = menuService.listMenu()
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/coded/spring/orders/menu/MenuRepository.kt b/src/main/kotlin/com/coded/spring/orders/menu/MenuRepository.kt
new file mode 100644
index 0000000..9def669
--- /dev/null
+++ b/src/main/kotlin/com/coded/spring/orders/menu/MenuRepository.kt
@@ -0,0 +1,27 @@
+package com.coded.spring.ordering.menu
+
+import jakarta.inject.Named
+import jakarta.persistence.*
+import org.springframework.data.jpa.repository.JpaRepository
+import java.math.BigDecimal
+
+@Named
+interface MenuRepository : JpaRepository{
+
+}
+
+@Entity
+@Table(name = "menu")
+data class MenuEntity(
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ var id: Long? = null,
+ var name: String,
+ var price: BigDecimal,
+ var description: String
+
+
+){
+ constructor() : this(null, "", BigDecimal.ZERO, "")
+}
diff --git a/src/main/kotlin/com/coded/spring/orders/menu/MenuService.kt b/src/main/kotlin/com/coded/spring/orders/menu/MenuService.kt
new file mode 100644
index 0000000..b40140c
--- /dev/null
+++ b/src/main/kotlin/com/coded/spring/orders/menu/MenuService.kt
@@ -0,0 +1,30 @@
+package com.coded.spring.ordering.menu
+
+import jakarta.inject.Named
+import org.springframework.beans.factory.annotation.Value
+import java.math.BigDecimal
+import java.math.RoundingMode
+
+@Named
+class MenuService(
+ private val menuRepository: MenuRepository,
+
+ @Value("\${feature.festive.enabled:false}")
+ val festiveStatus: Boolean,
+) {
+
+ fun listMenu(): List = menuRepository.findAll().map {
+ MenuEntity(
+ id = it.id,
+ name = it.name,
+ price = if(festiveStatus) {
+ // discount the price by 20%
+ it.price.multiply(BigDecimal("0.8"))
+ } else{
+ it.price
+ },
+ description = it.description
+ )
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/coded/spring/orders/profiles/ProfilesController.kt b/src/main/kotlin/com/coded/spring/orders/profiles/ProfilesController.kt
new file mode 100644
index 0000000..6329263
--- /dev/null
+++ b/src/main/kotlin/com/coded/spring/orders/profiles/ProfilesController.kt
@@ -0,0 +1,24 @@
+package com.coded.spring.ordering.profiles
+
+import io.swagger.v3.oas.annotations.tags.Tag
+import org.springframework.http.ResponseEntity
+import org.springframework.web.bind.annotation.PostMapping
+import org.springframework.web.bind.annotation.RequestBody
+import org.springframework.web.bind.annotation.RestController
+
+@Tag(name = "ProfileAPI")
+@RestController
+class ProfilesController(
+ private val profilesRepository: ProfilesRepository,
+ private val profilesService: ProfilesService
+){
+ // user creating profile
+ @PostMapping("/profile")
+ fun createOrUpdateProfile(@RequestBody request: ProfileRequestDto): Any {
+ try{
+ return profilesService.createOrUpdateProf(request)
+ } catch (e: IllegalArgumentException) {
+ return ResponseEntity.badRequest().body(mapOf("error" to e.message))
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/coded/spring/orders/profiles/ProfilesDTO.kt b/src/main/kotlin/com/coded/spring/orders/profiles/ProfilesDTO.kt
new file mode 100644
index 0000000..96fedea
--- /dev/null
+++ b/src/main/kotlin/com/coded/spring/orders/profiles/ProfilesDTO.kt
@@ -0,0 +1,16 @@
+package com.coded.spring.ordering.profiles
+
+import com.coded.spring.ordering.users.UserEntity
+
+data class ProfileRequestDto(
+ val firstName: String,
+ val lastName: String,
+ val phoneNumber: String
+)
+
+data class ProfileResponseDto(
+ 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/orders/profiles/ProfilesRepository.kt b/src/main/kotlin/com/coded/spring/orders/profiles/ProfilesRepository.kt
new file mode 100644
index 0000000..5bbf828
--- /dev/null
+++ b/src/main/kotlin/com/coded/spring/orders/profiles/ProfilesRepository.kt
@@ -0,0 +1,33 @@
+package com.coded.spring.ordering.profiles
+
+
+import com.coded.spring.ordering.users.UserEntity
+import jakarta.inject.Named
+import jakarta.persistence.*
+import org.springframework.data.jpa.repository.JpaRepository
+
+
+
+@Named
+interface ProfilesRepository : JpaRepository {
+ fun findByUserId(userId: UserEntity): ProfileEntity?
+}
+
+@Entity
+@Table(name = "profiles")
+data class ProfileEntity(
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ var id: Long? = null,
+
+ //one user can have one profile
+ @OneToOne
+ @JoinColumn(name = "user_id")// foreign key for Users(Id)
+ var userId: UserEntity,
+
+ var firstName: String,
+ var lastName: String,
+ var phoneNumber: String,
+
+){ constructor() : this(null, UserEntity(), "", "", "")
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/coded/spring/orders/profiles/ProfilesService.kt b/src/main/kotlin/com/coded/spring/orders/profiles/ProfilesService.kt
new file mode 100644
index 0000000..b08210f
--- /dev/null
+++ b/src/main/kotlin/com/coded/spring/orders/profiles/ProfilesService.kt
@@ -0,0 +1,55 @@
+package com.coded.spring.ordering.profiles
+
+import com.coded.spring.ordering.users.UsersRepository
+import jakarta.inject.Named
+import org.springframework.security.core.context.SecurityContextHolder
+import org.springframework.stereotype.Service
+
+@Service
+open class ProfilesService(
+ private val profilesRepository: ProfilesRepository,
+ private val usersRepository: UsersRepository
+) {
+
+ // create or update info for profiles
+ fun createOrUpdateProf(request: ProfileRequestDto): Any{
+
+ // get the username from the security contextholer
+ val username = SecurityContextHolder.getContext().authentication.name
+
+ // check if user exists
+ val user = usersRepository.findByUsername(username)
+ ?: throw IllegalArgumentException("user not found")
+
+ // check if user have a profile
+ val existingProfile = profilesRepository.findByUserId(user)
+
+ val profile = if( existingProfile != null){
+ // update existing profile
+ val updateProfile = existingProfile.copy(
+ firstName = request.firstName,
+ lastName = request.lastName,
+ phoneNumber = request.phoneNumber
+ )
+ profilesRepository.save(updateProfile)
+
+ } else { // if user doesn't have a profile
+ // create a new profile
+ val createProfile = ProfileEntity(
+ userId = user,
+ firstName = request.firstName,
+ lastName = request.lastName,
+ phoneNumber = request.phoneNumber,
+ )
+ profilesRepository.save(createProfile)
+ }
+
+ return ProfileResponseDto(
+ userId = user.id!!,
+ firstName = profile.firstName,
+ lastName = profile.lastName,
+ phoneNumber = profile.phoneNumber
+ )
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/coded/spring/orders/scripts/InitUserRunner.kt b/src/main/kotlin/com/coded/spring/orders/scripts/InitUserRunner.kt
new file mode 100644
index 0000000..a2bbb6d
--- /dev/null
+++ b/src/main/kotlin/com/coded/spring/orders/scripts/InitUserRunner.kt
@@ -0,0 +1,34 @@
+package com.coded.spring.ordering.scripts
+
+import com.coded.spring.ordering.users.UserEntity
+import com.coded.spring.ordering.users.UsersRepository
+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(usersRepository: UsersRepository, passwordEncoder: PasswordEncoder) = CommandLineRunner {
+ val user = UserEntity(
+ name = "HelloUser",
+ username = "testuser",
+ password = passwordEncoder.encode("password123"),
+ age = 18,
+
+ )
+ if (usersRepository.findByUsername(user.username) == null) {
+ println("Creating user ${user.username}")
+ usersRepository.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/resources/application.properties b/src/main/resources/application.properties
index 3704dc6..38fb0f0 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -1 +1,10 @@
spring.application.name=Kotlin.SpringbootV2
+
+server.port=8081
+
+spring.datasource.url=jdbc:postgresql://localhost:8080/myHelloDatabase
+spring.datasource.username=postgres
+spring.datasource.password=Barrak2000#
+spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
+
+springdoc.api-docs.path=/api-docs
diff --git a/src/test/kotlin/com/coded/spring/ordering/ApplicationTests.kt b/src/test/kotlin/com/coded/spring/ordering/ApplicationTests.kt
index b2e2320..18278f6 100644
--- a/src/test/kotlin/com/coded/spring/ordering/ApplicationTests.kt
+++ b/src/test/kotlin/com/coded/spring/ordering/ApplicationTests.kt
@@ -1,13 +1,347 @@
package com.coded.spring.ordering
+import RegistrationResponseDto
+import com.coded.spring.ordering.authentication.AuthRequest
+import com.coded.spring.ordering.authentication.AuthResponse
+import com.coded.spring.ordering.authentication.jwt.JwtService
+import com.coded.spring.ordering.items.CreateItemRequestDTO
+import com.coded.spring.ordering.items.ItemDTO
+import com.coded.spring.ordering.items.ItemsListDTO
+import com.coded.spring.ordering.items.ItemsRepository
+import com.coded.spring.ordering.orders.CreateOrderRequest
+import com.coded.spring.ordering.orders.OrderDTO
+import com.coded.spring.ordering.orders.OrderRepository
+import com.coded.spring.ordering.orders.OrdersListDTO
+import com.coded.spring.ordering.profiles.ProfileRequestDto
+import com.coded.spring.ordering.profiles.ProfileResponseDto
+import com.coded.spring.ordering.users.RegistrationRequest
+import com.coded.spring.ordering.users.UserEntity
+import com.coded.spring.ordering.users.UsersRepository
+import org.junit.jupiter.api.Assertions
+import org.junit.jupiter.api.Assertions.assertNotNull
+import org.junit.jupiter.api.BeforeAll
+import org.junit.jupiter.api.BeforeEach
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.context.SpringBootTest.WebEnvironment
+import org.springframework.boot.test.web.client.TestRestTemplate
+import org.springframework.boot.test.web.client.exchange
+import org.springframework.boot.test.web.client.getForEntity
+import org.springframework.boot.test.web.client.postForEntity
+import org.springframework.context.annotation.Profile
+import org.springframework.http.*
+import org.springframework.security.config.annotation.web.builders.HttpSecurity
+import org.springframework.security.crypto.password.PasswordEncoder
+import org.springframework.test.context.ActiveProfiles
+import org.springframework.util.MultiValueMap
+import kotlin.reflect.jvm.internal.impl.load.kotlin.JvmType
+import kotlin.test.assertEquals
+import kotlin.test.assertTrue
-@SpringBootTest
+@SpringBootTest(
+ webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
+)
class ApplicationTests {
+ companion object {
+ val testUser = "Yousef91"
+ val testPassword = "Test123456"
+
+ @JvmStatic
+ @BeforeAll
+ fun setup(
+
+ @Autowired usersRepository: UsersRepository,
+ @Autowired passwordEncoder: PasswordEncoder
+ ) {
+
+ val test = UserEntity(
+ name = "Yousef Al Othman",
+ age = 25,
+ username = testUser,
+ password = passwordEncoder.encode(testPassword)
+ )
+ usersRepository.save(test)
+ }
+ }
+
+ @Autowired
+ lateinit var restTemplate: TestRestTemplate
+ @Autowired
+ lateinit var usersRepository: UsersRepository
+
+ // a helper function to get jwt token
+ fun getAuthToken(): String {
+ // create a authentication request with test credentials
+ val login = AuthRequest(
+ username = testUser,
+ password = testPassword
+ )
+
+ // send an http post request to the login endpoint
+ val response: ResponseEntity = restTemplate.postForEntity(
+ "/authentication/login",
+ login,
+ AuthResponse::class.java
+ )
+
+ Assertions.assertEquals(HttpStatus.OK, response.statusCode) //check status code
+ assertNotNull(response.body) //check that response.body is not null
+
+ return response.body?.token ?: throw AssertionError("Token is null")
+
+ }
+
+ // function to create the authentication request
+ fun authRequest(body: T, token: String): HttpEntity{
+ val headers = HttpHeaders()
+ headers.setBearerAuth(token)
+ return HttpEntity(body, headers)
+ }
+
+
+ // 1st test
+ @Test
+ fun `As a user, I can login and get jwt token`(){
+ // create a authentication request with test credentials
+ val login = AuthRequest(
+ username = testUser,
+ password = testPassword
+ )
+
+ // send a http post request to the login endpoint
+ val response: ResponseEntity = restTemplate.postForEntity(
+ "/authentication/login",
+ login,
+ AuthResponse::class.java
+ )
+
+ Assertions.assertEquals(HttpStatus.OK, response.statusCode) //check status code
+ assertNotNull(response.body) //check that response.body is not null
+ }
+
+ //registration
+ @Test
+ fun `As a developer, I can test user regastration endpoint`(){
+ // create a regastration request
+ val regastration = RegistrationRequest(
+ username = "userRegistration",
+ password = testPassword,
+ age = 30,
+ name = "Nemo"
+ )
+
+ // send http post request to the regastration endpoint
+ val response: ResponseEntity = restTemplate.postForEntity(
+ "/register",
+ regastration,
+ RegistrationResponseDto::class.java
+ )
+
+ Assertions.assertEquals(HttpStatus.OK, response.statusCode) //check status code
+ Assertions.assertEquals("userRegistration", response.body?.username) // check if username matches
+ // Verify the user was saved in database
+ val savedUser = usersRepository.findByUsername("userRegistration")
+ assertNotNull(savedUser)
+
+ }
+
+
+
+ // 3rd test
+ @Test
+ fun `As a developer, I can test creating orders`(){
+ //get authentication token
+ val token = getAuthToken()
+
+ //get user id
+ val user = usersRepository.findByUsername(testUser)
+ assertNotNull(user)
+
+ // create order
+ val order = CreateOrderRequest(
+ userId = user?.id!!
+ )
+ //1st order
+ val response1: ResponseEntity = restTemplate.postForEntity(
+ "/orders/orders",
+ authRequest(order, token),
+ Any::class.java
+ )
+ assertEquals(HttpStatus.OK, response1.statusCode) // check status code
+
+ //2nd order
+ val response2: ResponseEntity = restTemplate.postForEntity(
+ "/orders/orders",
+ authRequest(order, token),
+ Any::class.java
+ )
+ assertEquals(HttpStatus.OK, response2.statusCode) // check status code
+
+
+ }// 4th test
@Test
- fun contextLoads() {
+ fun `As a developer, I can test reading orders list`(){
+ //get authentication token
+ val token = getAuthToken()
+
+ //get user id
+ val user = usersRepository.findByUsername(testUser)
+ assertNotNull(user)
+
+ // create order
+// val order = CreateOrderRequest(
+// userId = user?.id!!
+// )
+// //1st order
+// val response1: ResponseEntity = restTemplate.postForEntity(
+// "/orders/orders",
+// authRequest(order, token),
+// Any::class.java
+// )
+// assertEquals(HttpStatus.OK, response1.statusCode) // check status code
+//
+// //2nd order
+// val response2: ResponseEntity = restTemplate.postForEntity(
+// "/orders/orders",
+// authRequest(order, token),
+// Any::class.java
+// )
+// assertEquals(HttpStatus.OK, response2.statusCode) // check status code
+
+ // create authenticated get request
+ val headers = HttpHeaders()
+ headers.setBearerAuth(token)
+ val getRequest = HttpEntity(headers)
+
+ // get the orders
+ val response: ResponseEntity = restTemplate.exchange(
+ "/orders/orders",
+ HttpMethod.GET,
+ getRequest,
+ OrdersListDTO::class.java
+ )
+
+ assertEquals(HttpStatus.OK, response.statusCode) // check status code
+ val orders = response.body
+ assertNotNull(orders) // checking orders is not null
+ assertEquals(2, response.body?.orders?.size)// making sure there's 2 orders in the list
+
+ //verify all orders belong to the same user
+
+ }
+
+ //5th test
+ @Test
+ fun `as a developer, I can test a user can create profile`(){
+ val token = getAuthToken()
+
+ // create profile
+ val createProfile = ProfileRequestDto(
+ firstName = "Harvey",
+ lastName = "Specter",
+ phoneNumber = "333-111-3333"
+ )
+ //create response
+ val response: ResponseEntity = restTemplate.postForEntity(
+ "/profile",
+ authRequest(createProfile, token),
+ ProfileResponseDto::class.java
+ )
+ //verify responses
+ assertEquals(HttpStatus.OK, response.statusCode)
+ assertEquals("Harvey", response.body?.firstName)
+ assertEquals("Specter", response.body?.lastName)
+ assertEquals("333-111-3333", response.body?.phoneNumber)
+ }
+
+ //6th test
+ @Test
+ fun `as a developer, I can test a user can update profile`(){
+ val token = getAuthToken()
+
+ val updateProfile = ProfileRequestDto(
+ firstName = "Mike",
+ lastName = "Ross",
+ phoneNumber = "111-222-2222"
+ )
+ val response2: ResponseEntity = restTemplate.postForEntity(
+ "/profile",
+ authRequest(updateProfile, token),
+ ProfileResponseDto::class.java
+ )
+
+ assertEquals(HttpStatus.OK, response2.statusCode)
+ assertEquals("Mike", response2.body?.firstName)
+ assertEquals("Ross", response2.body?.lastName)
+ assertEquals("111-222-2222", response2.body?.phoneNumber)
+ }
+
+ //7th test
+ @Test
+ fun `As a developer, I can add items to an order`(){
+ val token = getAuthToken()
+
+ //get user id
+ val user = usersRepository.findByUsername(testUser)
+ assertNotNull(user)
+
+ // Add items to the order
+ val item1 = CreateItemRequestDTO(
+ name = "Machboos",
+ quantity = 1,
+ order_id = user?.id!!
+ )
+
+ val item2 = CreateItemRequestDTO(
+ name = "Laban",
+ quantity = 4,
+ order_id = user.id!!
+ )
+
+ // Create items
+ restTemplate.postForEntity(
+ "/items/create",
+ authRequest(item1, token),
+ ItemDTO::class.java
+ )
+
+ restTemplate.postForEntity(
+ "/items/create",
+ authRequest(item2, token),
+ ItemDTO::class.java
+ )
+
+ // Get the order id
+ val headers = HttpHeaders()
+ headers.setBearerAuth(token)
+ val getRequest = HttpEntity(headers)
+
+ // list items
+ val response: ResponseEntity = restTemplate.exchange(
+ "/orders/orders",
+ HttpMethod.GET,
+ getRequest,
+ ItemsListDTO::class.java
+
+ )
+ assertEquals(HttpStatus.OK, response.statusCode)
+ val items = response.body
+ assertNotNull(items)
+ }
+
+ //8th test
+ @Test
+ fun `as a developer, I can test reading the menu`(){
+
+ val response = restTemplate.getForEntity(
+ "/menu",
+ Object::class.java
+ )
+ assertEquals(HttpStatus.OK, response.statusCode)
+ assertNotNull(response)
+
}
-}
+}
\ No newline at end of file
diff --git a/src/test/resources/application-test.properties b/src/test/resources/application-test.properties
new file mode 100644
index 0000000..a3a4208
--- /dev/null
+++ b/src/test/resources/application-test.properties
@@ -0,0 +1,10 @@
+spring.application.name=Kotlin.SpringbootV2
+spring.datasource.url=jdbc:h2:mem:testdb
+spring.datasource.driverClassName=org.h2.Driver
+spring.datasource.username=sa
+spring.datasource.password=
+spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
+spring.jpa.hibernate.ddl-auto=create-drop
+spring.jpa.show-sql=true
+spring.h2.console.enabled=true
+spring.h2.console.path=/h2-console
\ No newline at end of file
diff --git a/target/classes/META-INF/Ordering.kotlin_module b/target/classes/META-INF/Ordering.kotlin_module
new file mode 100644
index 0000000..7f5d569
Binary files /dev/null and b/target/classes/META-INF/Ordering.kotlin_module differ
diff --git a/target/classes/RegistrationRequest.class b/target/classes/RegistrationRequest.class
new file mode 100644
index 0000000..f3623e0
Binary files /dev/null and b/target/classes/RegistrationRequest.class differ
diff --git a/target/classes/RegistrationRequestDTO.class b/target/classes/RegistrationRequestDTO.class
new file mode 100644
index 0000000..74ee737
Binary files /dev/null and b/target/classes/RegistrationRequestDTO.class differ
diff --git a/target/classes/RegistrationResponseDto.class b/target/classes/RegistrationResponseDto.class
new file mode 100644
index 0000000..1d2ee6c
Binary files /dev/null and b/target/classes/RegistrationResponseDto.class differ
diff --git a/target/classes/application.properties b/target/classes/application.properties
new file mode 100644
index 0000000..38fb0f0
--- /dev/null
+++ b/target/classes/application.properties
@@ -0,0 +1,10 @@
+spring.application.name=Kotlin.SpringbootV2
+
+server.port=8081
+
+spring.datasource.url=jdbc:postgresql://localhost:8080/myHelloDatabase
+spring.datasource.username=postgres
+spring.datasource.password=Barrak2000#
+spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
+
+springdoc.api-docs.path=/api-docs
diff --git a/target/classes/com/coded/spring/ordering/Application.class b/target/classes/com/coded/spring/ordering/Application.class
new file mode 100644
index 0000000..e3f99d2
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/Application.class differ
diff --git a/target/classes/com/coded/spring/ordering/ApplicationKt.class b/target/classes/com/coded/spring/ordering/ApplicationKt.class
new file mode 100644
index 0000000..0b09b10
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/ApplicationKt.class differ
diff --git a/target/classes/com/coded/spring/ordering/HelloWorldController.class b/target/classes/com/coded/spring/ordering/HelloWorldController.class
new file mode 100644
index 0000000..ed6e39d
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/HelloWorldController.class differ
diff --git a/target/classes/com/coded/spring/ordering/LoggingFilter.class b/target/classes/com/coded/spring/ordering/LoggingFilter.class
new file mode 100644
index 0000000..64c5e3a
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/LoggingFilter.class differ
diff --git a/target/classes/com/coded/spring/ordering/OrderRequest.class b/target/classes/com/coded/spring/ordering/OrderRequest.class
new file mode 100644
index 0000000..0708a13
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/OrderRequest.class differ
diff --git a/target/classes/com/coded/spring/ordering/SayMyNameRequest.class b/target/classes/com/coded/spring/ordering/SayMyNameRequest.class
new file mode 100644
index 0000000..77b2023
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/SayMyNameRequest.class differ
diff --git a/target/classes/com/coded/spring/ordering/authentication/AuthController.class b/target/classes/com/coded/spring/ordering/authentication/AuthController.class
new file mode 100644
index 0000000..be11d80
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/authentication/AuthController.class differ
diff --git a/target/classes/com/coded/spring/ordering/authentication/AuthRequest.class b/target/classes/com/coded/spring/ordering/authentication/AuthRequest.class
new file mode 100644
index 0000000..69e29e5
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/authentication/AuthRequest.class differ
diff --git a/target/classes/com/coded/spring/ordering/authentication/AuthResponse.class b/target/classes/com/coded/spring/ordering/authentication/AuthResponse.class
new file mode 100644
index 0000000..77e923f
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/authentication/AuthResponse.class differ
diff --git a/target/classes/com/coded/spring/ordering/authentication/CustomUserDetailsClass.class b/target/classes/com/coded/spring/ordering/authentication/CustomUserDetailsClass.class
new file mode 100644
index 0000000..2c6f1ee
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/authentication/CustomUserDetailsClass.class differ
diff --git a/target/classes/com/coded/spring/ordering/authentication/SecurityConfig.class b/target/classes/com/coded/spring/ordering/authentication/SecurityConfig.class
new file mode 100644
index 0000000..4c5b499
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/authentication/SecurityConfig.class differ
diff --git a/target/classes/com/coded/spring/ordering/authentication/jwt/JwtAuthFilter.class b/target/classes/com/coded/spring/ordering/authentication/jwt/JwtAuthFilter.class
new file mode 100644
index 0000000..148c5fc
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/authentication/jwt/JwtAuthFilter.class differ
diff --git a/target/classes/com/coded/spring/ordering/authentication/jwt/JwtService.class b/target/classes/com/coded/spring/ordering/authentication/jwt/JwtService.class
new file mode 100644
index 0000000..a28c871
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/authentication/jwt/JwtService.class differ
diff --git a/target/classes/com/coded/spring/ordering/items/CreateItemRequestDTO.class b/target/classes/com/coded/spring/ordering/items/CreateItemRequestDTO.class
new file mode 100644
index 0000000..fcc8905
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/items/CreateItemRequestDTO.class differ
diff --git a/target/classes/com/coded/spring/ordering/items/ItemDTO.class b/target/classes/com/coded/spring/ordering/items/ItemDTO.class
new file mode 100644
index 0000000..b64ad17
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/items/ItemDTO.class differ
diff --git a/target/classes/com/coded/spring/ordering/items/ItemEntity.class b/target/classes/com/coded/spring/ordering/items/ItemEntity.class
new file mode 100644
index 0000000..afbaba0
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/items/ItemEntity.class differ
diff --git a/target/classes/com/coded/spring/ordering/items/ItemsController.class b/target/classes/com/coded/spring/ordering/items/ItemsController.class
new file mode 100644
index 0000000..27e6fee
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/items/ItemsController.class differ
diff --git a/target/classes/com/coded/spring/ordering/items/ItemsListDTO.class b/target/classes/com/coded/spring/ordering/items/ItemsListDTO.class
new file mode 100644
index 0000000..3baa7cb
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/items/ItemsListDTO.class differ
diff --git a/target/classes/com/coded/spring/ordering/items/ItemsRepository.class b/target/classes/com/coded/spring/ordering/items/ItemsRepository.class
new file mode 100644
index 0000000..e583b4f
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/items/ItemsRepository.class differ
diff --git a/target/classes/com/coded/spring/ordering/items/ItemsService.class b/target/classes/com/coded/spring/ordering/items/ItemsService.class
new file mode 100644
index 0000000..f55b9eb
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/items/ItemsService.class differ
diff --git a/target/classes/com/coded/spring/ordering/menu/MenuController.class b/target/classes/com/coded/spring/ordering/menu/MenuController.class
new file mode 100644
index 0000000..05cc632
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/menu/MenuController.class differ
diff --git a/target/classes/com/coded/spring/ordering/menu/MenuEntity.class b/target/classes/com/coded/spring/ordering/menu/MenuEntity.class
new file mode 100644
index 0000000..2292ccc
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/menu/MenuEntity.class differ
diff --git a/target/classes/com/coded/spring/ordering/menu/MenuRepository.class b/target/classes/com/coded/spring/ordering/menu/MenuRepository.class
new file mode 100644
index 0000000..acf1906
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/menu/MenuRepository.class differ
diff --git a/target/classes/com/coded/spring/ordering/menu/MenuService.class b/target/classes/com/coded/spring/ordering/menu/MenuService.class
new file mode 100644
index 0000000..69c2a29
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/menu/MenuService.class differ
diff --git a/target/classes/com/coded/spring/ordering/orders/CreateOrderRequest.class b/target/classes/com/coded/spring/ordering/orders/CreateOrderRequest.class
new file mode 100644
index 0000000..1b921d5
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/orders/CreateOrderRequest.class differ
diff --git a/target/classes/com/coded/spring/ordering/orders/OrderController.class b/target/classes/com/coded/spring/ordering/orders/OrderController.class
new file mode 100644
index 0000000..fb704e5
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/orders/OrderController.class differ
diff --git a/target/classes/com/coded/spring/ordering/orders/OrderDTO.class b/target/classes/com/coded/spring/ordering/orders/OrderDTO.class
new file mode 100644
index 0000000..3ec9afe
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/orders/OrderDTO.class differ
diff --git a/target/classes/com/coded/spring/ordering/orders/OrderEntity.class b/target/classes/com/coded/spring/ordering/orders/OrderEntity.class
new file mode 100644
index 0000000..9e5df7b
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/orders/OrderEntity.class differ
diff --git a/target/classes/com/coded/spring/ordering/orders/OrderRepository.class b/target/classes/com/coded/spring/ordering/orders/OrderRepository.class
new file mode 100644
index 0000000..14e7759
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/orders/OrderRepository.class differ
diff --git a/target/classes/com/coded/spring/ordering/orders/OrderService.class b/target/classes/com/coded/spring/ordering/orders/OrderService.class
new file mode 100644
index 0000000..2a09901
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/orders/OrderService.class differ
diff --git a/target/classes/com/coded/spring/ordering/orders/OrdersListDTO.class b/target/classes/com/coded/spring/ordering/orders/OrdersListDTO.class
new file mode 100644
index 0000000..f4be656
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/orders/OrdersListDTO.class differ
diff --git a/target/classes/com/coded/spring/ordering/profiles/ProfileEntity.class b/target/classes/com/coded/spring/ordering/profiles/ProfileEntity.class
new file mode 100644
index 0000000..b1d7fdc
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/profiles/ProfileEntity.class differ
diff --git a/target/classes/com/coded/spring/ordering/profiles/ProfileRequestDto.class b/target/classes/com/coded/spring/ordering/profiles/ProfileRequestDto.class
new file mode 100644
index 0000000..235ecf0
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/profiles/ProfileRequestDto.class differ
diff --git a/target/classes/com/coded/spring/ordering/profiles/ProfileResponseDto.class b/target/classes/com/coded/spring/ordering/profiles/ProfileResponseDto.class
new file mode 100644
index 0000000..e245afb
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/profiles/ProfileResponseDto.class differ
diff --git a/target/classes/com/coded/spring/ordering/profiles/ProfilesController.class b/target/classes/com/coded/spring/ordering/profiles/ProfilesController.class
new file mode 100644
index 0000000..2d2a34d
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/profiles/ProfilesController.class differ
diff --git a/target/classes/com/coded/spring/ordering/profiles/ProfilesRepository.class b/target/classes/com/coded/spring/ordering/profiles/ProfilesRepository.class
new file mode 100644
index 0000000..6ab7791
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/profiles/ProfilesRepository.class differ
diff --git a/target/classes/com/coded/spring/ordering/profiles/ProfilesService.class b/target/classes/com/coded/spring/ordering/profiles/ProfilesService.class
new file mode 100644
index 0000000..1a8c8e6
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/profiles/ProfilesService.class differ
diff --git a/target/classes/com/coded/spring/ordering/scripts/InitUserRunner.class b/target/classes/com/coded/spring/ordering/scripts/InitUserRunner.class
new file mode 100644
index 0000000..fff4b84
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/scripts/InitUserRunner.class differ
diff --git a/target/classes/com/coded/spring/ordering/scripts/InitUserRunnerKt.class b/target/classes/com/coded/spring/ordering/scripts/InitUserRunnerKt.class
new file mode 100644
index 0000000..0816720
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/scripts/InitUserRunnerKt.class differ
diff --git a/target/classes/com/coded/spring/ordering/users/RegistrationRequest.class b/target/classes/com/coded/spring/ordering/users/RegistrationRequest.class
new file mode 100644
index 0000000..cbcd90d
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/users/RegistrationRequest.class differ
diff --git a/target/classes/com/coded/spring/ordering/users/Roles.class b/target/classes/com/coded/spring/ordering/users/Roles.class
new file mode 100644
index 0000000..41c35f8
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/users/Roles.class differ
diff --git a/target/classes/com/coded/spring/ordering/users/User.class b/target/classes/com/coded/spring/ordering/users/User.class
new file mode 100644
index 0000000..b477edb
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/users/User.class differ
diff --git a/target/classes/com/coded/spring/ordering/users/UserEntity.class b/target/classes/com/coded/spring/ordering/users/UserEntity.class
new file mode 100644
index 0000000..7a50ab4
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/users/UserEntity.class differ
diff --git a/target/classes/com/coded/spring/ordering/users/UsersController.class b/target/classes/com/coded/spring/ordering/users/UsersController.class
new file mode 100644
index 0000000..d26b022
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/users/UsersController.class differ
diff --git a/target/classes/com/coded/spring/ordering/users/UsersRepository.class b/target/classes/com/coded/spring/ordering/users/UsersRepository.class
new file mode 100644
index 0000000..23b64d5
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/users/UsersRepository.class differ
diff --git a/target/classes/com/coded/spring/ordering/users/UsersService.class b/target/classes/com/coded/spring/ordering/users/UsersService.class
new file mode 100644
index 0000000..e3edb67
Binary files /dev/null and b/target/classes/com/coded/spring/ordering/users/UsersService.class differ
diff --git a/target/test-classes/META-INF/Ordering.kotlin_module b/target/test-classes/META-INF/Ordering.kotlin_module
new file mode 100644
index 0000000..1e9f2ca
Binary files /dev/null and b/target/test-classes/META-INF/Ordering.kotlin_module differ
diff --git a/target/test-classes/application-test.properties b/target/test-classes/application-test.properties
new file mode 100644
index 0000000..a3a4208
--- /dev/null
+++ b/target/test-classes/application-test.properties
@@ -0,0 +1,10 @@
+spring.application.name=Kotlin.SpringbootV2
+spring.datasource.url=jdbc:h2:mem:testdb
+spring.datasource.driverClassName=org.h2.Driver
+spring.datasource.username=sa
+spring.datasource.password=
+spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
+spring.jpa.hibernate.ddl-auto=create-drop
+spring.jpa.show-sql=true
+spring.h2.console.enabled=true
+spring.h2.console.path=/h2-console
\ No newline at end of file
diff --git a/target/test-classes/com/coded/spring/ordering/ApplicationTests$Companion.class b/target/test-classes/com/coded/spring/ordering/ApplicationTests$Companion.class
new file mode 100644
index 0000000..e9f9714
Binary files /dev/null and b/target/test-classes/com/coded/spring/ordering/ApplicationTests$Companion.class differ
diff --git a/target/test-classes/com/coded/spring/ordering/ApplicationTests.class b/target/test-classes/com/coded/spring/ordering/ApplicationTests.class
new file mode 100644
index 0000000..0941ff6
Binary files /dev/null and b/target/test-classes/com/coded/spring/ordering/ApplicationTests.class differ