Skip to content
This repository has been archived by the owner on Aug 13, 2022. It is now read-only.

Commit

Permalink
Merge pull request #3 from f-lab-edu/feature/1
Browse files Browse the repository at this point in the history
[#1] Create Account
  • Loading branch information
jjeda committed Sep 23, 2019
2 parents cd545ba + 403d321 commit 58257f2
Show file tree
Hide file tree
Showing 26 changed files with 1,163 additions and 5 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ Commerce 가 제공하는 기능들을 직접 구현함으로써 대규모 트
- 이벤트(남/여, 연령 등 카테고리화 -> 선착순 이벤트 )

## 포스팅
- [@AuthenticationPrincipal - 현재 사용자 조회하기](https://jjeda.tistory.com/7)
- [@AuthenticationPrincipal - 현재 사용자 조회하기](https://jjeda.tistory.com/7)

12 changes: 8 additions & 4 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,21 @@
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
Expand Down
71 changes: 71 additions & 0 deletions src/main/java/me/jjeda/mall/accounts/Service/AccountService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package me.jjeda.mall.accounts.Service;

import me.jjeda.mall.accounts.domain.Account;
import me.jjeda.mall.accounts.domain.AccountAdapter;
import me.jjeda.mall.accounts.domain.AccountStatus;
import me.jjeda.mall.accounts.dto.AccountDto;
import me.jjeda.mall.accounts.repository.AccountRepository;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PagedResourcesAssembler;
import org.springframework.hateoas.PagedResources;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Optional;

@Service
public class AccountService implements UserDetailsService {

private AccountRepository accountRepository;

private PasswordEncoder passwordEncoder;

public AccountService(AccountRepository accountRepository, PasswordEncoder passwordEncoder) {
this.accountRepository = accountRepository;
this.passwordEncoder = passwordEncoder;
}

public Account saveAccount(AccountDto dto) {
Account account = dto.toEntity();
account.setPassword(passwordEncoder.encode(dto.getPassword()));

return accountRepository.save(account);
}

public PagedResources findAllAccountWithStatus(AccountStatus status, Pageable pageable, PagedResourcesAssembler<Account> pagedResourcesAssembler) {

return pagedResourcesAssembler.toResource(accountRepository.findAccountsByStatus(status, pageable));

}

public Optional<Account> getAccount(Long id) {
return accountRepository.findById(id);
}

@Transactional
public void changeAccountStatus(Long id, AccountStatus status) {
Account account = accountRepository.findById(id).get();
account.setStatus(status);
}

@Transactional
public Account updateAccount(Long id, AccountDto accountDto) {
Account account = accountRepository.findById(id).get();
account.update(accountDto);

return account;
}

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Account account = accountRepository.findByEmail(username)
.orElseThrow(() -> new UsernameNotFoundException(username));

return AccountAdapter.from(account);
}

}
60 changes: 60 additions & 0 deletions src/main/java/me/jjeda/mall/accounts/configs/AuthServerConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package me.jjeda.mall.accounts.configs;

import me.jjeda.mall.accounts.Service.AccountService;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;

@Configuration
@EnableAuthorizationServer
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {

private PasswordEncoder passwordEncoder;

private AuthenticationManager authenticationManager;

private AccountService accountService;

private TokenStore tokenStore;

public AuthServerConfig(PasswordEncoder passwordEncoder, AuthenticationManager authenticationManager, AccountService accountService, TokenStore tokenStore) {
this.passwordEncoder = passwordEncoder;
this.authenticationManager = authenticationManager;
this.accountService = accountService;
this.tokenStore = tokenStore;
}

// 보안정보 설정
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.passwordEncoder(passwordEncoder);
}

// 클라이언트 설정
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient("temp")
.authorizedGrantTypes("password", "refresh_token")
.scopes("read", "write")
.secret(this.passwordEncoder.encode("pass"))
.accessTokenValiditySeconds(10 * 60)
.refreshTokenValiditySeconds(6 * 10 * 60);
}

// 엔드포인트 정보 설정
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.authenticationManager(authenticationManager)
.userDetailsService(accountService)
.tokenStore(tokenStore);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package me.jjeda.mall.accounts.configs;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class PasswordEncoderConfig {

/**
* password : 평문 Hashing 처리를 위한 메서드
*
* @return : Bcrypt Encoder
*/
@Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package me.jjeda.mall.accounts.configs;

import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler;

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId("account");
}

@Override
public void configure(HttpSecurity http) throws Exception {
http
.anonymous()
.and()
.authorizeRequests()
.mvcMatchers(HttpMethod.POST,"/api/accounts")
.anonymous()
.mvcMatchers("/api/accounts/**")
.authenticated()
.mvcMatchers(HttpMethod.GET, "/api/**")
.permitAll()
.mvcMatchers("/admin/**").hasRole("ADMIN")
.anyRequest()
.authenticated()
.and()
.exceptionHandling()
.accessDeniedHandler(new OAuth2AccessDeniedHandler());
}

}
69 changes: 69 additions & 0 deletions src/main/java/me/jjeda/mall/accounts/configs/SecurityConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package me.jjeda.mall.accounts.configs;

import me.jjeda.mall.accounts.Service.AccountService;
import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

private AccountService accountService;

private PasswordEncoder passwordEncoder;

public SecurityConfig(AccountService accountService, PasswordEncoder passwordEncoder) {
this.accountService = accountService;
this.passwordEncoder = passwordEncoder;
}


/**
* TokenStore -> Redis
*/
@Bean
public TokenStore tokenStore(RedisConnectionFactory redisConnectionFactory) {
return new RedisTokenStore(redisConnectionFactory);
}


@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(accountService)
.passwordEncoder(passwordEncoder);
}

@Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors().disable()
.csrf().disable()
.formLogin().disable()
.headers().frameOptions().disable();

}

@Override
public void configure(WebSecurity web) throws Exception {
//정적 파일들 허용
web.ignoring().requestMatchers(PathRequest.toStaticResources().atCommonLocations());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package me.jjeda.mall.accounts.controller;

import me.jjeda.mall.accounts.Service.AccountService;
import me.jjeda.mall.accounts.domain.Account;
import me.jjeda.mall.accounts.domain.AccountStatus;
import me.jjeda.mall.accounts.dto.AccountDto;
import me.jjeda.mall.common.CurrentUser;
import org.springframework.hateoas.mvc.ControllerLinkBuilder;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.net.URI;

@RestController
@RequestMapping("/api/accounts")
public class AccountController {

private AccountService accountService;

public AccountController(AccountService accountService) {
this.accountService = accountService;
}

@PostMapping
public ResponseEntity createAccount(@RequestBody @Valid AccountDto requestAccount) {
Account account = accountService.saveAccount(requestAccount);
URI uri = ControllerLinkBuilder.linkTo(AccountController.class).slash(account.getId()).toUri();

return ResponseEntity.created(uri).body(account);
}

@GetMapping
public ResponseEntity getAccount(@CurrentUser Account account) {
return ResponseEntity.ok(account);
}

@DeleteMapping
public ResponseEntity withdrawFromMembership(@CurrentUser Account account) {
accountService.changeAccountStatus(account.getId(), AccountStatus.DELETED);

return ResponseEntity.ok().build();
}

@PutMapping
public ResponseEntity updateAccount(@RequestBody @Valid AccountDto accountDto, @CurrentUser Account account) {
Account updateAccount = accountService.updateAccount(account.getId(), accountDto);

return ResponseEntity.ok(updateAccount);
}
}
Loading

0 comments on commit 58257f2

Please sign in to comment.