Skip to content
Open

FFN #19

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions WelcomeToOnlineOrdering.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.coded.spring.ordering

import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController

@RestController

class WelcomeToOnlineOrdering {

@GetMapping("/")
fun welcome(): String{
return "Your Order Await"
}

}
20 changes: 20 additions & 0 deletions main/kotlin/com/coded/spring/ordering/Application.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.coded.spring.ordering

import org.springframework.boot.CommandLineRunner
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.autoconfigure.domain.EntityScan
import org.springframework.boot.runApplication
import org.springframework.context.annotation.Bean
import org.springframework.data.jpa.repository.config.EnableJpaRepositories
import org.springframework.security.crypto.password.PasswordEncoder

@SpringBootApplication
//@EntityScan("com.coded.spring.ordering") // <- your package
//@EnableJpaRepositories(basePackages = ["com.coded.spring.ordering"])


class Application

fun main(args: Array<String>) {
runApplication<Application>(*args)
}
36 changes: 36 additions & 0 deletions main/kotlin/com/coded/spring/ordering/InitUserRunner.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.coded.spring.ordering

import com.coded.spring.ordering.user.UserEntity
import com.coded.spring.ordering.user.UsersRepository
import org.springframework.boot.CommandLineRunner
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.context.annotation.Bean
import org.springframework.security.crypto.password.PasswordEncoder
import org.springframework.boot.runApplication
import org.springframework.stereotype.Component

//@SpringBootApplication
//@Component
//class InitUserRunner {
// @Bean
// fun initUsers(userRepository: UsersRepository, passwordEncoder: PasswordEncoder) = CommandLineRunner {
// val user = UserEntity(
// id =null,
// name ="Fatma",
// age = 23,
// username = "FFN",
// password = passwordEncoder.encode("123"),
//
// )
// if (userRepository.findByUsername(user.username) == null) {
// println("Creating user ${user.username}")
// userRepository.save(user)
// } else {
// println("User ${user.username} already exists")
// }
// }
//}

//fun main(args: Array<String>) {
// runApplication<InitUserRunner>(*args).close()
//}
15 changes: 15 additions & 0 deletions main/kotlin/com/coded/spring/ordering/WelcomeToOnlineOrdering.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.coded.spring.ordering

import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController

@RestController

class WelcomeToOnlineOrdering {

@GetMapping("/hello")
fun welcome(): String{
return "Your Order Await"
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.coded.spring.ordering.auth


import org.springframework.security.authentication.AuthenticationManager
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
import org.springframework.security.core.userdetails.UserDetailsService
import org.springframework.security.core.userdetails.UsernameNotFoundException
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
@RequestMapping("/auth")
class AuthenticationController(
private val authenticationManager: AuthenticationManager,
private val userDetailsService: UserDetailsService,
private val jwtService: JwtService
) {

@PostMapping("/login")
fun login(@RequestBody authRequest: AuthenticationRequest): AuthenticationResponse {
val authToken = UsernamePasswordAuthenticationToken(authRequest.username, authRequest.password)
val authentication = authenticationManager.authenticate(authToken)

if (authentication.isAuthenticated) {
val userDetails = userDetailsService.loadUserByUsername(authRequest.username)
val token = jwtService.generateToken(userDetails.username)
return AuthenticationResponse(token)
} else {
throw UsernameNotFoundException("Invalid user request!")
}
}
}

data class AuthenticationRequest(
val username: String,
val password: String
)

data class AuthenticationResponse(
val token: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.coded.spring.ordering.auth


import com.coded.spring.ordering.user.UserEntity
import com.coded.spring.ordering.user.UsersRepository
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
//@Service
class CustomerUserDetailsService(
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)
.authorities("USER")
.build()


}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.coded.spring.ordering.auth

import jakarta.servlet.FilterChain
import jakarta.servlet.http.*
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.core.userdetails.UserDetailsService
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource
import org.springframework.stereotype.Component
import org.springframework.web.filter.OncePerRequestFilter

@Component
class JwtAuthenticationFilter(
private val jwtService: JwtService,
private val userDetailsService: UserDetailsService
) : OncePerRequestFilter() {

override fun doFilterInternal(
request: HttpServletRequest,
response: HttpServletResponse,
filterChain: FilterChain
) {
val authHeader = request.getHeader("Authorization")
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
filterChain.doFilter(request, response)
return
}

val token = authHeader.substring(7)
val username = jwtService.extractUsername(token)

if (SecurityContextHolder.getContext().authentication == null) {
if (jwtService.isTokenValid(token, username)) {
val userDetails = userDetailsService.loadUserByUsername(username)
val authToken = UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.authorities
)
authToken.details = WebAuthenticationDetailsSource().buildDetails(request)
SecurityContextHolder.getContext().authentication = authToken
}
}

filterChain.doFilter(request, response)
}
}
43 changes: 43 additions & 0 deletions main/kotlin/com/coded/spring/ordering/auth/JwtService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.coded.spring.ordering.auth
import jakarta.inject.Named

import io.jsonwebtoken.Jwts
import io.jsonwebtoken.SignatureAlgorithm
import io.jsonwebtoken.security.Keys
import org.springframework.stereotype.Component
import java.util.Date
import javax.crypto.SecretKey
@Named
@Component
class JwtService {

private val secretKey: SecretKey = Keys.secretKeyFor(SignatureAlgorithm.HS256)
private val expirationMs: Long = 1000 * 60 * 60

fun generateToken(username: String): String {
val now = Date()
val expiry = Date(now.time + expirationMs)

return Jwts.builder()
.setSubject(username)
.setIssuedAt(now)
.setExpiration(expiry)
.signWith(secretKey)
.compact()
}

fun extractUsername(token: String): String =
Jwts.parserBuilder()
.setSigningKey(secretKey)
.build()
.parseClaimsJws(token)
.body.subject

fun isTokenValid(token: String, username: String): Boolean {
return try {
extractUsername(token) == username
} catch (e: Exception) {
false
}
}
}
58 changes: 58 additions & 0 deletions main/kotlin/com/coded/spring/ordering/auth/SecurityConfig.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.coded.spring.ordering.auth

import com.coded.spring.ordering.auth.JwtAuthenticationFilter
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.security.authentication.AuthenticationManager
import org.springframework.security.authentication.AuthenticationProvider
import org.springframework.security.authentication.dao.DaoAuthenticationProvider
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
import org.springframework.security.config.http.SessionCreationPolicy
import org.springframework.security.core.userdetails.UserDetailsService
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
import org.springframework.security.crypto.password.PasswordEncoder
import org.springframework.security.web.SecurityFilterChain
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter



@Configuration
@EnableWebSecurity
class SecurityConfig(
private val jwtAuthFilter: JwtAuthenticationFilter,
private val userDetailsService: UserDetailsService
) {

@Bean
fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
http.csrf { it.disable() }
.authorizeHttpRequests {
it.requestMatchers("/auth/**").permitAll()
.anyRequest().authenticated()
}
.sessionManagement {
it.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
}
.authenticationProvider(authenticationProvider())
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter::class.java)

return http.build()
}

@Bean
fun passwordEncoder(): PasswordEncoder = BCryptPasswordEncoder()

@Bean
fun authenticationManager(config: AuthenticationConfiguration): AuthenticationManager =
config.authenticationManager

@Bean
fun authenticationProvider(): AuthenticationProvider {
val provider = DaoAuthenticationProvider()
provider.setUserDetailsService(userDetailsService)
provider.setPasswordEncoder(passwordEncoder())
return provider
}
}
17 changes: 17 additions & 0 deletions main/kotlin/com/coded/spring/ordering/item/ItemDTO.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.coded.spring.ordering.item

data class Item(
val id: Long?,
val order_id: Long?,
val name: String?,
val quantity: Long?,
val note: String?,
val price: Double?
)

data class SubmitItemRequest(
val name: String,
val quantity: Long,
val note: String?,
val price: Double
)
29 changes: 29 additions & 0 deletions main/kotlin/com/coded/spring/ordering/item/ItemEntity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.coded.spring.ordering.item

import com.coded.spring.ordering.order.OrderEntity
import jakarta.persistence.*

@Entity
@Table(name = "items")
data class ItemEntity(

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long? = null,

@Column(name = "items")
var name: String? = null,

var quantity: Long? = null,

var note: String? = null,

var price: Double? = null,

@ManyToOne
@JoinColumn(name = "order_id")
var order: OrderEntity? = null

) {
constructor() : this(null, "", 1, "", 0.0, null)
}
5 changes: 5 additions & 0 deletions main/kotlin/com/coded/spring/ordering/item/ItemRepo.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.coded.spring.ordering.item

import org.springframework.data.jpa.repository.JpaRepository

interface ItemsRepository : JpaRepository<ItemEntity, Long>
16 changes: 16 additions & 0 deletions main/kotlin/com/coded/spring/ordering/item/ItemServ.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.coded.spring.ordering.item

import jakarta.inject.Named

@Named
class ItemsServ(private val itemsRepository: ItemsRepository) {
fun listItems(): List<Item> = itemsRepository.findAll().map { entity ->
Item(id = entity.id, order_id = entity.order?.id, name = entity.name, quantity = entity.quantity, note = entity.note, price = entity.price)
}

fun submitItem(request: SubmitItemRequest): ItemEntity {
val item = ItemEntity(name = request.name, quantity = request.quantity, note = request.note, price = request.price)
return itemsRepository.save(item)
}

}
Loading