Skip to content

Commit

Permalink
Merge pull request #12 from dbflute-example/feature/sample-api
Browse files Browse the repository at this point in the history
Add Sample Api
  • Loading branch information
miyasama committed Jul 28, 2024
2 parents 8a5fee2 + 3718c13 commit 7ee1638
Show file tree
Hide file tree
Showing 19 changed files with 587 additions and 27 deletions.
16 changes: 16 additions & 0 deletions api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,31 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest-jsonb</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-openapi</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-jwt</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-jwt-build</artifactId>
</dependency>

<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
<!-- Partner Library -->
<!-- = = = = = = = = -->
<!-- Quarkus -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-validator</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
Expand Down
24 changes: 0 additions & 24 deletions api/src/main/java/org/docksidestage/app/SampleResource.java

This file was deleted.

27 changes: 27 additions & 0 deletions api/src/main/java/org/docksidestage/app/base/PagingForm.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package org.docksidestage.app.base;

import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;

import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.ws.rs.DefaultValue;
import jakarta.ws.rs.QueryParam;

/**
* @author miyasama
*/
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public class PagingForm {

@QueryParam("page")
@DefaultValue(value = "1")
@Min(value = 1)
public Integer page;

@QueryParam("page_size")
@DefaultValue(value = "50")
@Min(value = 1)
@Max(value = 100)
public Integer pageSize;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package org.docksidestage.app.base;

import java.util.List;

import org.dbflute.Entity;
import org.dbflute.cbean.result.PagingResultBean;

import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;

/**
* @author miyasama
*/
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public class SearchPagingResult<BEAN> {

/** row count per one page */
public final int pageSize;

/** number of current page */
public final int currentPageNumber;

/** count of all records */
public final int allRecordCount;

/** count of all pages */
public final int allPageCount;

/** paging data for current page */
@NotNull
@Valid
public final List<BEAN> rows;

public SearchPagingResult(PagingResultBean<? extends Entity> page, List<BEAN> rows) {
this.pageSize = page.getPageSize();
this.currentPageNumber = page.getCurrentPageNumber();
this.allRecordCount = page.getAllRecordCount();
this.allPageCount = page.getAllPageCount();
this.rows = rows;
}
}
107 changes: 107 additions & 0 deletions api/src/main/java/org/docksidestage/app/lido/auth/AuthController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package org.docksidestage.app.lido.auth;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.time.ZoneOffset;

import org.docksidestage.dbflute.exbhv.MemberBhv;
import org.docksidestage.dbflute.exbhv.MemberLoginBhv;
import org.docksidestage.dbflute.exbhv.MemberSecurityBhv;
import org.docksidestage.dbflute.exbhv.MemberServiceBhv;
import org.docksidestage.dbflute.exentity.Member;
import org.docksidestage.dbflute.exentity.MemberLogin;
import org.docksidestage.interceptor.accesscontext.AccessContext;
import org.eclipse.microprofile.config.Config;
import org.eclipse.microprofile.jwt.JsonWebToken;

import io.quarkus.security.AuthenticationFailedException;
import io.smallrye.jwt.auth.principal.JWTParser;
import io.smallrye.jwt.build.Jwt;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.validation.Valid;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

/**
* @author miyasama
*/
@Path("/auth")
@ApplicationScoped
public class AuthController {

// ===================================================================================
// Attribute
//
@Inject
MemberBhv memberBhv;

@Inject
MemberSecurityBhv memberSecurityBhv;

@Inject
MemberServiceBhv memberServiceBhv;

@Inject
MemberLoginBhv memberLoginBhv;

@Inject
JsonWebToken jwt;

@Inject
JWTParser jwtParser;

@Inject
Config config;

@POST
@Path("/signin")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@AccessContext
public SigninResult search(@Valid SigninBody body) {
var member = memberBhv.selectEntity(cb -> {
cb.query().arrangeLogin(body.account, encryptPassword(body.password));
}).orElseThrow(() -> new AuthenticationFailedException());

insertLogin(member);

var jwt = issueJwt(member);

var result = new SigninResult();
result.jwt = jwt;
return result;
}

private String encryptPassword(String value) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(value.getBytes());
return String.format("%064x", new BigInteger(1, md.digest()));
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("パスワードの暗号化に失敗しました。", e);
}
}

private String issueJwt(Member member) {
return Jwt.issuer(config.getValue("mp.jwt.verify.issuer", String.class))
.expiresAt(LocalDateTime.now().plusMonths(1).toInstant(ZoneOffset.UTC)) // 有効期限を30日後に設定
.upn(member.getMemberId().toString()) //
.claim("name", member.getMemberName())
.sign();
}

private void insertLogin(Member member) {
MemberLogin login = new MemberLogin();
login.setMemberId(member.getMemberId());
login.setLoginMemberStatusCodeAsMemberStatus(member.getMemberStatusCodeAsMemberStatus());
login.setLoginDatetime(LocalDateTime.now());
login.setMobileLoginFlg_False();
memberLoginBhv.insert(login);
}
}
15 changes: 15 additions & 0 deletions api/src/main/java/org/docksidestage/app/lido/auth/SigninBody.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.docksidestage.app.lido.auth;

import jakarta.validation.constraints.NotBlank;

/**
* @author miyasama
*/
public class SigninBody {

@NotBlank
public String account;

@NotBlank
public String password;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.docksidestage.app.lido.auth;

import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;

import jakarta.validation.constraints.NotBlank;

/**
* @author miyasama
*/
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public class SigninResult {

@NotBlank
public String jwt;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package org.docksidestage.app.lido.mypage;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import org.docksidestage.dbflute.exbhv.ProductBhv;

import io.quarkus.security.Authenticated;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.SecurityContext;

/**
* @author miyasama
*/
@Path("/mypage")
@Authenticated
@ApplicationScoped
public class MyPageController {

// ===================================================================================
// Attribute
//
@Inject
ProductBhv productBhv;

@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("/products")
public List<MypageProductResult> index(@Context SecurityContext ctx) {
var loginUserId = Optional.ofNullable(ctx.getUserPrincipal()).map(user -> Long.parseLong(user.getName())).orElse(null);
System.out.println(loginUserId);
//TODO Refine data by logged-in user ID

var memberList = productBhv.selectList(cb -> {
cb.query().addOrderBy_RegularPrice_Desc();
cb.fetchFirst(3);
});

return memberList.stream().map(product -> {
var result = new MypageProductResult();
result.productName = product.getProductName();
result.regularPrice = product.getRegularPrice();
return result;
}).collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.docksidestage.app.lido.mypage;

import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;

import jakarta.validation.constraints.NotBlank;

/**
* @author miyasama
*/
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public class MypageProductResult {

@NotBlank
public String productName;

public int regularPrice;
}
Loading

0 comments on commit 7ee1638

Please sign in to comment.