Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jsoup 연습 및 token TTL 적용 #161

Merged
merged 7 commits into from
Nov 27, 2016
Merged
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
27 changes: 6 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ The word ‘K LEAGUE JAKDU KING’ is formed by combining ‘K LEAGUE’, ‘JAK
The MIT License (MIT)

### Slack
If you join Slack, it's possible to talk.
If you join Slack, it's possible to talk. Please send email to me(phjang1983@daum.net), then send to an invitation email.
* https://jakduk.slack.com

### Finding contributors
Expand All @@ -31,26 +31,11 @@ This project is based on IntelliJ IDEA and Eclipse. You can import the project u
#### Dependency Management
* Gradle

#### Continuous integration Tool
* Jenkins

#### Database
* mongoDB

#### WAS
* Apache tmocat 8.x

#### Spring Framework 4.x
* Spring Core
* Spring Mvc
* Spring Security
* Spring Social
* Spring Data

#### Front end (CSS, Javascript)
* Bower
* Bootstrap
* JQuery
* AngularJS
* [Summernote](https://github.com/HackerWins/summernote), [angular-summernote](https://github.com/outsideris/angular-summernote)
* font-awesome
* Highcharts
* Slick

#### Spring Framework
* Spring Boot
1 change: 0 additions & 1 deletion api/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ dependencies {

compile 'io.springfox:springfox-swagger2:2.6.1'
compile 'io.springfox:springfox-swagger-ui:2.6.1'
compile 'org.springframework.data:spring-data-rest-hal-browser:2.5.1.RELEASE'
compile 'io.jsonwebtoken:jjwt:0.7.0'
}

This file was deleted.

18 changes: 8 additions & 10 deletions api/src/main/java/com/jakduk/api/configuration/SecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
Expand Down Expand Up @@ -65,23 +66,20 @@ protected void configure(HttpSecurity http) throws Exception {
.antMatchers(
"/api/login", // 로그인
"/auth/*", // SNS 인증
"/signup", // SNS 계정으로 회원 가입
"/user/social", // OAUTH2 콜백
"/user/write", // JakduK 회원 가입
"/user/*/write", // SNS 계정으로 회원 가입
"/password/*" // 비밀번호 찾기
"/signup" // SNS 계정으로 회원 가입
).anonymous()
.antMatchers(
HttpMethod.POST,
"/api/user", // 이메일 기반 회원 가입
"/api/user/social" // SNS 기반 회원 가입
).anonymous()
.antMatchers(
"/user/**",
// "/swagger-ui.html", // 스웨거
"/rest/**" // spring-data-rest
).authenticated()

// RESTful로 전환했기 때문에 바뀌어야 한다
.antMatchers(
"/board/*/write",
"/board/*/edit",
"/jakdu/write"

).hasAnyRole("USER_01", "USER_02", "USER_03")
.antMatchers(
"/admin/**",
Expand Down
24 changes: 15 additions & 9 deletions api/src/main/java/com/jakduk/api/configuration/SwaggerConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger.web.ApiKeyVehicle;
import springfox.documentation.swagger.web.SecurityConfiguration;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

Expand Down Expand Up @@ -46,6 +49,7 @@ public Docket api() {
.host(environment.getProperty("swagger.host"))
.apiInfo(apiInfo())
.useDefaultResponseMessages(false)
.securitySchemes(Collections.singletonList(apiKey()))
.produces(producesList);
}

Expand All @@ -58,18 +62,20 @@ SecurityConfiguration security() {
"test-app",
"",
ApiKeyVehicle.HEADER,
"Authorization",
"",
"," /*scope separator*/);
}

private ApiInfo apiInfo() {
return new ApiInfo(
"JakduK REST API",
"Some custom description of API.",
"API TOS",
"Terms of service",
new Contact("pio.", "https://jakduk.com", "phjang1983@daum.net"),
"License of API",
"https://github.com/JakduK/JakduK/blob/master/LICENSE");
return new ApiInfoBuilder()
.title("JakduK REST API with Swagger")
.contact(new Contact("pio.", "https://jakduk.com", "phjang1983@daum.net"))
.license("The MIT License (MIT)")
.licenseUrl("https://github.com/JakduK/jakduk-api/blob/master/LICENSE")
.build();
}

private ApiKey apiKey() {
return new ApiKey("Authorization", "api_key", "header");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,15 @@
import com.jakduk.core.service.UserService;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.LocaleResolver;

import javax.annotation.Resource;
import javax.mail.MessagingException;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.*;

@Slf4j
@Api(tags = "User", description = "회원 API")
Expand All @@ -51,15 +46,11 @@ public class PasswordRestController {
@Autowired
private EmailService emailService;

@Value("#{tokenTerminationTrigger.span}")
private long tokenSpan;

// jakduk 비밀번호 찾기 처리.
@RequestMapping(value = "/find", method = RequestMethod.POST)
public Map<String, Object> findPassword(@RequestParam String email,
@RequestParam String callbackUrl,
final Locale locale) {

Locale locale) {
String message = "";

UserProfile userProfile = userService.findOneByEmail(email);
Expand All @@ -71,6 +62,7 @@ public Map<String, Object> findPassword(@RequestParam String email,
case JAKDUK:
message = CoreUtils.getResourceBundleMessage("messages.user", "user.msg.reset.password.sendok");
try {

emailService.sendResetPassword(locale, callbackUrl, email);
} catch (MessagingException e) {
throw new ServiceException(ServiceError.SEND_EMAIL_FAILED);
Expand All @@ -95,21 +87,18 @@ public Map<String, Object> findPassword(@RequestParam String email,

// jakduk 비밀번호 재설정.
@RequestMapping(value = "/reset/{code}", method = RequestMethod.GET)
public Map<String, Object> resetPassword(@PathVariable String code,
HttpServletRequest request) {

Locale locale = localeResolver.resolveLocale(request);
public Map<String, Object> resetPassword(@PathVariable String code) {

if (Objects.isNull(code))
throw new IllegalArgumentException(CoreUtils.getExceptionMessage("exception.invalid.parameter"));

Map<String, Object> response = new HashMap<>();
Token token = commonService.getTokenByCode(code);
Optional<Token> oToken = commonService.getTokenByCode(code);

if (Objects.isNull(token) || !token.getCode().equals(code)) {
if (! oToken.isPresent() || ! StringUtils.equals(oToken.get().getCode(), code))
throw new IllegalArgumentException(CoreUtils.getResourceBundleMessage("messages.user", "user.msg.reset.password.invalid"));
}

Token token = oToken.get();
response.put("subject", token.getEmail());
response.put("code", token.getCode());

Expand All @@ -122,22 +111,20 @@ public Map<String, Object> updatePassword(
@RequestParam(value = "password") String password,
@RequestParam(value = "code") String code) {

long tokenSpanMillis = TimeUnit.MINUTES.toMillis(tokenSpan);
Token token = tokenRepository.findByCode(code);
Optional<Token> oToken = commonService.getTokenByCode(code);

Map<String, Object> response = new HashMap<>();
String message;

if (Objects.isNull(token) || token.getCreatedTime().getTime() + tokenSpanMillis <= System.currentTimeMillis()) {
message = CoreUtils.getResourceBundleMessage("messages.user", "user.msg.reset.password.invalid");
} else {
if (oToken.isPresent()) {
Token token = oToken.get();
userService.userPasswordUpdateByEmail(token.getEmail(), passwordEncoder.encode(password.trim()));
message = CoreUtils.getResourceBundleMessage("messages.user", "user.msg.success.change.password");
response.put("subject", token.getEmail());
}

if (Objects.nonNull(token)) {
tokenRepository.delete(token);
} else {
message = CoreUtils.getResourceBundleMessage("messages.user", "user.msg.reset.password.invalid");
}

response.put("message", message);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ public Boolean existUsernameOnAnonymous(@RequestParam() String username,

@ApiOperation(value = "이메일 중복 검사")
@RequestMapping(value = "/exist/email", method = RequestMethod.GET)
public EmptyJsonResponse existEmail(@NotEmpty @Email @RequestParam String email) {
public EmptyJsonResponse existEmail(@Valid @NotEmpty @Email @RequestParam String email) {

userService.existEmail(email.trim());

Expand All @@ -186,7 +186,7 @@ public EmptyJsonResponse existEmail(@NotEmpty @Email @RequestParam String email)

@ApiOperation(value = "별명 중복 검사")
@RequestMapping(value = "/exist/username", method = RequestMethod.GET)
public EmptyJsonResponse existUsername(@NotEmpty @RequestParam String username) {
public EmptyJsonResponse existUsername(@Valid @NotEmpty @RequestParam String username) {

userService.existUsername(username.trim());

Expand Down
3 changes: 2 additions & 1 deletion api/src/test/java/com/jakduk/api/AdminTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.jakduk.core.repository.board.free.BoardFreeRepositoryRepository;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.web.util.UrlUtils;

/**
* @author <a href="mailto:phjang1983@daum.net">Jang,Pyohwan</a>
Expand All @@ -27,7 +28,7 @@ public void getBoard() {
long boardCnt = 101;
int limit = 100;
int totalPage = (int)(boardCnt / limit);

System.out.println("boardCnt=" + boardCnt);
System.out.println("totalPage=" + totalPage);
}
Expand Down
2 changes: 0 additions & 2 deletions api/src/test/java/com/jakduk/api/common/CommonTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@
import com.jakduk.core.service.CommonService;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Spy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.crypto.password.StandardPasswordEncoder;

Expand Down
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ subprojects {

compile group: 'org.jongo', name: 'jongo', version:'1.3.0'
compile group: 'commons-fileupload', name: 'commons-fileupload', version:'1.3.2'
compile group: 'commons-io', name: 'commons-io', version:'2.4'
compile group: 'commons-io', name: 'commons-io', version:'2.5'
compile group: 'rome', name: 'rome', version:'1.0'
compile group: 'io.searchbox', name: 'jest', version:'2.0.3'
compile group: 'net.gpedro.integrations.slack', name: 'slack-webhook', version:'1.1.1'
compile 'commons-beanutils:commons-beanutils:1.9.2'
compile group: 'net.gpedro.integrations.slack', name: 'slack-webhook', version:'1.2.1'
compile 'commons-beanutils:commons-beanutils:1.9.3'
compile 'net.coobird:thumbnailator:0.4.8'

compileOnly 'org.projectlombok:lombok:1.16.10'
Expand Down
2 changes: 2 additions & 0 deletions changelog/db_migration.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// token TTL 설정
db.token.ensureIndex( { "expireAt": 1 }, { expireAfterSeconds: 0 } )

Version 0.7.0 / 2016-07-27

Expand Down
1 change: 1 addition & 0 deletions core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ description = 'core'

dependencies {
compile 'javax.persistence:persistence-api:1.0.2'
compile 'org.jsoup:jsoup:1.10.1'
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.jakduk.core.configuration;

import com.jakduk.core.trigger.TokenTerminationTrigger;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
Expand All @@ -20,14 +19,6 @@
@EnableAsync
public class CoreAsyncConfig implements AsyncConfigurer {

@Bean(initMethod = "init")
public TokenTerminationTrigger tokenTerminationTrigger() {
TokenTerminationTrigger tokenTerminationTrigger = new TokenTerminationTrigger();
tokenTerminationTrigger.setSpan(5);

return tokenTerminationTrigger;
}

@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
Expand Down
3 changes: 1 addition & 2 deletions core/src/main/java/com/jakduk/core/model/db/Token.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@ public class Token {

@Id
private String email;

private String code;
private CommonConst.TOKEN_TYPE tokenType = CommonConst.TOKEN_TYPE.RESET_PASSWORD;

@Temporal(TemporalType.DATE)
private Date createdTime;
private Date expireAt;
}
Loading