Task: Completed login and get token from user and able to change user password by username and updated the security filters and add auth service and auth details. And more add login mutation in resolver
This commit is contained in:
parent
9202c52640
commit
ceaacc9685
@ -1 +1 @@
|
|||||||
Subproject commit 9a114dba23c52619955999f867bc1b95d3870bb3
|
Subproject commit d69f52fee0d6c8c0fad3eab64dc0645470168a49
|
@ -9,7 +9,6 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
|
|||||||
@EnableWebMvc
|
@EnableWebMvc
|
||||||
class WebConfig : WebMvcConfigurer {
|
class WebConfig : WebMvcConfigurer {
|
||||||
override fun addCorsMappings(corsRegistry: CorsRegistry) {
|
override fun addCorsMappings(corsRegistry: CorsRegistry) {
|
||||||
println("Hello World")
|
|
||||||
corsRegistry.addMapping("/**")
|
corsRegistry.addMapping("/**")
|
||||||
.allowedOrigins("*")
|
.allowedOrigins("*")
|
||||||
.allowedMethods("*")
|
.allowedMethods("*")
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package com.cubetiqs.graphql.demo.config
|
package com.cubetiqs.graphql.demo.config
|
||||||
|
|
||||||
import com.cubetiqs.graphql.demo.secutiry.AuthService
|
import com.cubetiqs.graphql.demo.security.AuthService
|
||||||
import com.cubetiqs.security.jwt.AuthenticationExceptionEntryPoint
|
import com.cubetiqs.security.jwt.AuthenticationExceptionEntryPoint
|
||||||
import com.cubetiqs.security.jwt.JwtSecurityConfigurer
|
import com.cubetiqs.security.jwt.JwtSecurityConfigurer
|
||||||
import org.springframework.beans.factory.annotation.Autowired
|
import org.springframework.beans.factory.annotation.Autowired
|
||||||
@ -13,26 +13,25 @@ import org.springframework.security.config.http.SessionCreationPolicy
|
|||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
|
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||||
class WebSecurityConfig : WebSecurityConfigurerAdapter() {
|
class WebSecurityConfig : WebSecurityConfigurerAdapter() {
|
||||||
@Autowired
|
@Autowired
|
||||||
private lateinit var authService: AuthService
|
private lateinit var authService: AuthService
|
||||||
|
|
||||||
override fun configure(http: HttpSecurity) {
|
override fun configure(http: HttpSecurity) {
|
||||||
http.csrf()
|
http.csrf().disable()
|
||||||
.and()
|
|
||||||
.httpBasic()
|
|
||||||
.disable()
|
|
||||||
.sessionManagement()
|
.sessionManagement()
|
||||||
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
||||||
.and()
|
|
||||||
|
http
|
||||||
.exceptionHandling()
|
.exceptionHandling()
|
||||||
.authenticationEntryPoint(AuthenticationExceptionEntryPoint())
|
.authenticationEntryPoint(AuthenticationExceptionEntryPoint())
|
||||||
.and()
|
|
||||||
|
http
|
||||||
.apply(JwtSecurityConfigurer(authService))
|
.apply(JwtSecurityConfigurer(authService))
|
||||||
.and()
|
|
||||||
|
http
|
||||||
.authorizeRequests()
|
.authorizeRequests()
|
||||||
.anyRequest()
|
.anyRequest().permitAll()
|
||||||
.permitAll()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,6 +6,7 @@ import org.springframework.data.domain.Pageable
|
|||||||
import org.springframework.data.jpa.repository.JpaRepository
|
import org.springframework.data.jpa.repository.JpaRepository
|
||||||
import org.springframework.data.jpa.repository.Query
|
import org.springframework.data.jpa.repository.Query
|
||||||
import org.springframework.stereotype.Repository
|
import org.springframework.stereotype.Repository
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
interface UserRepository : JpaRepository<User, Long> {
|
interface UserRepository : JpaRepository<User, Long> {
|
||||||
@ -14,4 +15,7 @@ interface UserRepository : JpaRepository<User, Long> {
|
|||||||
|
|
||||||
@Query("select (count(u) > 0) from User u where u.username = ?1")
|
@Query("select (count(u) > 0) from User u where u.username = ?1")
|
||||||
fun existsAllByUsername(username: String): Boolean
|
fun existsAllByUsername(username: String): Boolean
|
||||||
|
|
||||||
|
@Query("select u from User u where u.username = ?1")
|
||||||
|
fun queryByUsername(username: String): Optional<User>
|
||||||
}
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package com.cubetiqs.graphql.demo.resolver.mutation
|
||||||
|
|
||||||
|
import com.cubetiqs.graphql.demo.context.GMutation
|
||||||
|
import com.cubetiqs.graphql.demo.dgmodel.DgsConstants
|
||||||
|
import com.cubetiqs.graphql.demo.dgmodel.types.LoginResponse
|
||||||
|
import com.cubetiqs.graphql.demo.security.AuthService
|
||||||
|
import com.cubetiqs.security.jwt.util.JwtUtils
|
||||||
|
import com.netflix.graphql.dgs.DgsMutation
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired
|
||||||
|
|
||||||
|
@GMutation
|
||||||
|
class LoginMutationResolver {
|
||||||
|
@Autowired
|
||||||
|
private lateinit var authService: AuthService
|
||||||
|
|
||||||
|
@DgsMutation(field = DgsConstants.MUTATION.Login)
|
||||||
|
fun login(username: String, password: String): LoginResponse {
|
||||||
|
val auth = authService.login(username, password)
|
||||||
|
val token = JwtUtils.encryptToken(auth)
|
||||||
|
return LoginResponse(token)
|
||||||
|
}
|
||||||
|
}
|
@ -2,11 +2,14 @@ package com.cubetiqs.graphql.demo.resolver.mutation
|
|||||||
|
|
||||||
import com.cubetiqs.graphql.demo.context.GMutation
|
import com.cubetiqs.graphql.demo.context.GMutation
|
||||||
import com.cubetiqs.graphql.demo.dgmodel.DgsConstants
|
import com.cubetiqs.graphql.demo.dgmodel.DgsConstants
|
||||||
|
import com.cubetiqs.graphql.demo.dgmodel.types.UserChangePasswordInput
|
||||||
import com.cubetiqs.graphql.demo.domain.user.User
|
import com.cubetiqs.graphql.demo.domain.user.User
|
||||||
import com.cubetiqs.graphql.demo.domain.user.UserInput
|
import com.cubetiqs.graphql.demo.domain.user.UserInput
|
||||||
import com.cubetiqs.graphql.demo.domain.user.UserMapper
|
import com.cubetiqs.graphql.demo.domain.user.UserMapper
|
||||||
import com.cubetiqs.graphql.demo.repository.UserRepository
|
import com.cubetiqs.graphql.demo.repository.UserRepository
|
||||||
|
import com.cubetiqs.security.jwt.util.JwtUtils
|
||||||
import com.netflix.graphql.dgs.DgsMutation
|
import com.netflix.graphql.dgs.DgsMutation
|
||||||
|
import com.netflix.graphql.dgs.exceptions.DgsEntityNotFoundException
|
||||||
import org.springframework.beans.factory.annotation.Autowired
|
import org.springframework.beans.factory.annotation.Autowired
|
||||||
import org.springframework.transaction.annotation.Propagation
|
import org.springframework.transaction.annotation.Propagation
|
||||||
import org.springframework.transaction.annotation.Transactional
|
import org.springframework.transaction.annotation.Transactional
|
||||||
@ -18,9 +21,16 @@ class UserMutationResolver @Autowired constructor(
|
|||||||
@DgsMutation(field = DgsConstants.MUTATION.CreateUser)
|
@DgsMutation(field = DgsConstants.MUTATION.CreateUser)
|
||||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||||
fun createUser(input: UserInput): User {
|
fun createUser(input: UserInput): User {
|
||||||
if (userRepository.existsAllByUsername(input.username ?: "")) throw Exception("Username has been already existed!")
|
if (userRepository.existsAllByUsername(input.username ?: "")) throw DgsEntityNotFoundException("Username has been already existed!")
|
||||||
|
|
||||||
val user = UserMapper.fromInputToUser(input)
|
val user = UserMapper.fromInputToUser(input)
|
||||||
return userRepository.save(user)
|
return userRepository.save(user)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@DgsMutation(field = DgsConstants.MUTATION.ChangeUserPassword)
|
||||||
|
fun changePassword(input: UserChangePasswordInput): User {
|
||||||
|
val user = userRepository.queryByUsername(input.username).orElse(null) ?: throw DgsEntityNotFoundException("User not found!")
|
||||||
|
user.password = JwtUtils.passwordEncoder().encode(input.password)
|
||||||
|
return userRepository.save(user)
|
||||||
|
}
|
||||||
}
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
package com.cubetiqs.graphql.demo.security
|
||||||
|
|
||||||
|
import com.cubetiqs.graphql.demo.domain.user.User
|
||||||
|
import com.cubetiqs.security.jwt.util.JwtUtils
|
||||||
|
import org.springframework.security.core.GrantedAuthority
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails
|
||||||
|
|
||||||
|
data class AuthDetails(
|
||||||
|
private var code: String? = null,
|
||||||
|
private var name: String? = null,
|
||||||
|
private var username: String? = null,
|
||||||
|
private var password: String? = null,
|
||||||
|
private var authorities: Collection<String>? = null,
|
||||||
|
private var enabled: Boolean? = null,
|
||||||
|
) : UserDetails {
|
||||||
|
override fun getAuthorities(): MutableCollection<out GrantedAuthority> {
|
||||||
|
return authorities?.map { SimpleGrantedAuthority(it) }?.toMutableList() ?: mutableListOf(
|
||||||
|
SimpleGrantedAuthority(
|
||||||
|
"USER"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getPassword(): String {
|
||||||
|
return password ?: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getUsername(): String {
|
||||||
|
return username ?: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isAccountNonExpired(): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isAccountNonLocked(): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isCredentialsNonExpired(): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isEnabled(): Boolean {
|
||||||
|
return enabled ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isPasswordValid(password: String): Boolean {
|
||||||
|
return JwtUtils.passwordEncoder().matches(password, this.getPassword())
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun fromUser(user: User): AuthDetails {
|
||||||
|
return AuthDetails(
|
||||||
|
code = user.code,
|
||||||
|
name = user.name,
|
||||||
|
username = user.username,
|
||||||
|
password = user.password,
|
||||||
|
enabled = user.enabled,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package com.cubetiqs.graphql.demo.security
|
||||||
|
|
||||||
|
import com.cubetiqs.graphql.demo.repository.UserRepository
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired
|
||||||
|
import org.springframework.security.access.AccessDeniedException
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsService
|
||||||
|
import org.springframework.stereotype.Service
|
||||||
|
|
||||||
|
@Service
|
||||||
|
class AuthService : UserDetailsService {
|
||||||
|
@Autowired
|
||||||
|
private lateinit var userRepository: UserRepository
|
||||||
|
|
||||||
|
private fun findAuthDetailsByUsername(username: String): AuthDetails {
|
||||||
|
val user = userRepository.queryByUsername(username).orElse(null) ?: throw Exception("User not found!")
|
||||||
|
return AuthDetails.fromUser(user)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun loadUserByUsername(username: String?): UserDetails {
|
||||||
|
return findAuthDetailsByUsername(username ?: "")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun login(username: String, password: String): AuthDetails {
|
||||||
|
val auth = findAuthDetailsByUsername(username)
|
||||||
|
if (auth.isPasswordValid(password)) {
|
||||||
|
return auth
|
||||||
|
} else {
|
||||||
|
throw AccessDeniedException("Username and password is incorrect!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +0,0 @@
|
|||||||
package com.cubetiqs.graphql.demo.secutiry
|
|
||||||
|
|
||||||
import org.springframework.security.core.userdetails.UserDetails
|
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService
|
|
||||||
import org.springframework.stereotype.Service
|
|
||||||
|
|
||||||
@Service
|
|
||||||
class AuthService : UserDetailsService {
|
|
||||||
override fun loadUserByUsername(username: String?): UserDetails {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
}
|
|
@ -15,7 +15,10 @@ type Subscription {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Mutation {
|
type Mutation {
|
||||||
|
login(username: String!, password: String!): LoginResponse
|
||||||
|
|
||||||
createUser(input: UserInput): User!
|
createUser(input: UserInput): User!
|
||||||
|
changeUserPassword(input: UserChangePasswordInput): User!
|
||||||
|
|
||||||
openAccount(input: AccountInput): Account!
|
openAccount(input: AccountInput): Account!
|
||||||
}
|
}
|
@ -12,3 +12,12 @@ input UserInput {
|
|||||||
name: String
|
name: String
|
||||||
enabled: Boolean
|
enabled: Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type LoginResponse {
|
||||||
|
token: String
|
||||||
|
}
|
||||||
|
|
||||||
|
input UserChangePasswordInput {
|
||||||
|
username: String!
|
||||||
|
password: String!
|
||||||
|
}
|
@ -40,23 +40,23 @@ const HELLO = gql`
|
|||||||
`
|
`
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
// const {error, loading, data} = useQuery<AccountResult>(ACCOUNTS)
|
const {error, loading, data} = useQuery<AccountResult>(ACCOUNTS)
|
||||||
const {error, loading, data} = useSubscription(HELLO)
|
// const {error, loading, data} = useSubscription(HELLO)
|
||||||
console.log(data)
|
console.log(data)
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h1>Accounts</h1>
|
<h1>Accounts</h1>
|
||||||
{
|
{
|
||||||
loading || !data ? <p>Loading...</p> :
|
loading || !data ? <p>Loading...</p> :
|
||||||
// data.fetchAccounts.map(account => (
|
data.fetchAccounts.map(account => (
|
||||||
// <>
|
<>
|
||||||
// <div>Account ID: {account.id}</div>
|
<div>Account ID: {account.id}</div>
|
||||||
// <div>Account Code: {account.code}</div>
|
<div>Account Code: {account.code}</div>
|
||||||
// <div>Account User: {account.user.name}</div>
|
<div>Account User: {account.user.name}</div>
|
||||||
// </>
|
</>
|
||||||
// )
|
)
|
||||||
// )
|
)
|
||||||
<p>{`${data.hello}`}</p>
|
// <p>{`${data.hello}`}</p>
|
||||||
}
|
}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user