Skip to content

Commit

Permalink
Merge pull request #10 from DDD-3/develop
Browse files Browse the repository at this point in the history
master <= develop
  • Loading branch information
y2o2u2n authored Nov 30, 2019
2 parents 292d371 + 36c2ea6 commit 5426cdc
Show file tree
Hide file tree
Showing 35 changed files with 945 additions and 32 deletions.
1 change: 1 addition & 0 deletions cloudbuild-deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ steps:
id: Install
args:
- 'install'
- '-P${_PROFILE}'
- name: 'gcr.io/cloud-builders/docker'
id: Build
args:
Expand Down
1 change: 1 addition & 0 deletions cloudbuild.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ steps:
id: Install
args:
- 'install'
- '-P${_PROFILE}'
- name: 'gcr.io/cloud-builders/docker'
id: Build
args:
Expand Down
64 changes: 53 additions & 11 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,38 +19,80 @@
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>

<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</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>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>2.3.2</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<spring.profiles.active>dev</spring.profiles.active>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<spring.profiles.active>prod</spring.profiles.active>
</properties>
</profile>
</profiles>

<build>
<finalName>app</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
Expand Down
18 changes: 0 additions & 18 deletions src/main/java/com/ddd/airplane/HelloWorldController.java

This file was deleted.

18 changes: 18 additions & 0 deletions src/main/java/com/ddd/airplane/accounts/Account.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.ddd.airplane.accounts;

import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.*;

import java.io.Serializable;
import java.util.Set;

@Getter @Setter @EqualsAndHashCode(of = "email")
@Builder @NoArgsConstructor @AllArgsConstructor
class Account implements Serializable {
private String email;
@JsonIgnore
private String password;
private String nickname;
@JsonIgnore
private Set<AccountRole> roles;
}
24 changes: 24 additions & 0 deletions src/main/java/com/ddd/airplane/accounts/AccountAdapter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.ddd.airplane.accounts;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;

import java.util.Collection;
import java.util.stream.Collectors;

class AccountAdapter extends User {
private Account account;

AccountAdapter(Account account) {
super(account.getEmail(), account.getPassword(), authorities(account.getRoles()));
this.account = account;
}

private static Collection<? extends GrantedAuthority> authorities(Collection<AccountRole> roles) {
return roles.stream().map(AccountRole::toAuthority).collect(Collectors.toList());
}

public Account getAccount() {
return account;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.ddd.airplane.accounts;

import com.ddd.airplane.common.AlreadyRegisteredException;

class AccountAlreadyRegisteredException extends AlreadyRegisteredException {
AccountAlreadyRegisteredException(String message) {
super(message);
}
}
29 changes: 29 additions & 0 deletions src/main/java/com/ddd/airplane/accounts/AccountApiController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.ddd.airplane.accounts;

import lombok.AllArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;

@AllArgsConstructor
@RestController
@RequestMapping("/api")
public class AccountApiController {
private final AccountService accountService;

@PostMapping("/v1/accounts")
@ResponseStatus(HttpStatus.CREATED)
public Account createAccount(@RequestBody @Valid AccountDto accountDto) {
return accountService.createAccount(accountDto);
}

@GetMapping("/v1/accounts/{email}")
@ResponseStatus(HttpStatus.OK)
public Account getAccount(
@PathVariable String email,
@CurrentAccount Account account
) {
return accountService.getAccount(email);
}
}
15 changes: 15 additions & 0 deletions src/main/java/com/ddd/airplane/accounts/AccountDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.ddd.airplane.accounts;

import lombok.Builder;
import lombok.Data;

import javax.validation.constraints.NotBlank;

@Data @Builder
public class AccountDto {
@NotBlank
private String email;
@NotBlank
private String password;
private String nickname;
}
51 changes: 51 additions & 0 deletions src/main/java/com/ddd/airplane/accounts/AccountRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.ddd.airplane.accounts;

import lombok.AllArgsConstructor;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import java.util.Set;

@AllArgsConstructor
@Repository
public class AccountRepository {
private final JdbcTemplate jdbcTemplate;

Account findByEmail(String email) {
try {
return jdbcTemplate.queryForObject(
AccountSql.FIND_BY_EMAIL,
new Object[]{email},
(rs, rowNum) -> Account.builder()
.email(rs.getString("email"))
.password(rs.getString("password"))
.nickname(rs.getString("nickname"))
.roles(Set.of(AccountRole.ROLE_USER))
.build()
);
} catch (EmptyResultDataAccessException e) {
return null;
}
}

Account save(Account account) {
jdbcTemplate.update(
AccountSql.SAVE,
account.getEmail(),
account.getPassword(),
account.getNickname()
);

return Account.builder()
.email(account.getEmail())
.nickname(account.getNickname())
.build();
}

void truncate() {
jdbcTemplate.update(
AccountSql.TRUNCATE
);
}
}
12 changes: 12 additions & 0 deletions src/main/java/com/ddd/airplane/accounts/AccountRole.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.ddd.airplane.accounts;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;

public enum AccountRole {
ROLE_USER;

public GrantedAuthority toAuthority() {
return new SimpleGrantedAuthority(name());
}
}
53 changes: 53 additions & 0 deletions src/main/java/com/ddd/airplane/accounts/AccountService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.ddd.airplane.accounts;

import lombok.AllArgsConstructor;
import org.modelmapper.ModelMapper;
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;

@AllArgsConstructor
@Service
public class AccountService implements UserDetailsService {
private final AccountRepository accountRepository;
private final ModelMapper modelMapper;
private final PasswordEncoder passwordEncoder;

public Account createAccount(AccountDto accountDto) {
String email = accountDto.getEmail();

if (accountRepository.findByEmail(email) != null) {
throw new AccountAlreadyRegisteredException(email);
}

Account account = modelMapper.map(accountDto, Account.class);
account.setPassword(passwordEncoder.encode(account.getPassword()));

return accountRepository.save(account);
}

Account getAccount(String email) {
Account account = accountRepository.findByEmail(email);
if (account == null) {
account = new Account();
}

return account;
}

public void deleteAll() {
accountRepository.truncate();
}

@Override
public UserDetails loadUserByUsername(String username) {
Account account = accountRepository.findByEmail(username);
if (account == null) {
throw new UsernameNotFoundException(username);
}

return new AccountAdapter(account);
}
}
8 changes: 8 additions & 0 deletions src/main/java/com/ddd/airplane/accounts/AccountSql.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.ddd.airplane.accounts;

class AccountSql {
static final String FIND_BY_EMAIL = "SELECT email, password, nickname FROM accounts WHERE email = ?";
static final String SAVE = "INSERT INTO accounts (email, password, nickname) VALUES (?, ?, ?)";
static final String TRUNCATE = "TRUNCATE TABLE accounts";
}

15 changes: 15 additions & 0 deletions src/main/java/com/ddd/airplane/accounts/CurrentAccount.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.ddd.airplane.accounts;


import org.springframework.security.core.annotation.AuthenticationPrincipal;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : account")
@interface CurrentAccount {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.ddd.airplane.common;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(HttpStatus.CONFLICT)
public class AlreadyRegisteredException extends RuntimeException {
public AlreadyRegisteredException(String message) {
super(message);
}
}
12 changes: 12 additions & 0 deletions src/main/java/com/ddd/airplane/common/AppProperties.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.ddd.airplane.common;

import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
@Getter
public class AppProperties {
@Value("${client.id}") private String clientId;
@Value("${client.secret}") private String clientSecret;
}
Loading

0 comments on commit 5426cdc

Please sign in to comment.