読者です 読者をやめる 読者になる 読者になる

かんがるーさんの日記

最近自分が興味をもったものを調べた時の手順等を書いています。今は Spring Boot をいじっています。

Spring Boot で書籍の貸出状況確認・貸出申請する Web アプリケーションを作る ( その52 )( 貸出申請結果確認画面の作成4 )

概要

Spring Boot で書籍の貸出状況確認・貸出申請する Web アプリケーションを作る ( その51 )( 貸出申請結果確認画面の作成3 ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • 貸出申請結果確認画面の作成
      • 貸出申請したユーザでなければ、共通エラー画面を表示し HTTPステータスコードの 403 を返す処理の実装

参照したサイト・書籍

目次

  1. messages_ja_JP.properties にエラーメッセージを定義する
  2. ConfirmresultForm, ConfirmresultService クラスの変更
  3. ConfirmresultController クラスの変更
  4. 動作確認
  5. 次回は。。。

手順

messages_ja_JP.properties にエラーメッセージを定義する

  1. src/main/resources の下の messages_ja_JP.properties を リンク先の内容 に変更します。

ConfirmresultForm, ConfirmresultService クラスの変更

ログインユーザが貸出申請したユーザか否かを判断するのにユーザID を使用したいので、ユーザID を Controller クラスまで返すようにします。

  1. src/main/java/ksbysample/webapp/lending/web/confirmresult の下の ConfirmresultForm.javaリンク先の内容 に変更します。

  2. src/main/java/ksbysample/webapp/lending/web/confirmresult の下の ConfirmresultService.javaリンク先の内容 に変更します。

ConfirmresultController クラスの変更

  1. src/main/java/ksbysample/webapp/lending/web/confirmresult の下の ConfirmresultController.javaリンク先の内容 に変更します。

動作確認

  1. 動作確認します。Gradle projects View から bootRun タスクを実行して Tomcat を起動します。

  2. http://localhost:8080/confirmresult?lendingAppId=105 にアクセスします。最初はログイン画面が表示されますので ID に "tanaka.taro@sample.com"、Password に "taro" を入力して、「次回から自動的にログインする」をチェックせずに「ログイン」ボタンをクリックします。

    "tanaka taro" は貸出申請したユーザなので貸出申請結果確認画面が表示されます。

    f:id:ksby:20160207021059p:plain

  3. 一旦ログアウトした後、再度 http://localhost:8080/confirmresult?lendingAppId=105 にアクセスします。ログイン画面が表示されますので今度は ID に "suzuki.hanako@test.co.jp"、Password に "hanako" を入力して、「次回から自動的にログインする」をチェックせずに「ログイン」ボタンをクリックします。

    "suzuki.hanako" は貸出申請したユーザではないので共通エラー画面が表示されます。

    f:id:ksby:20160207021533p:plain

    Fiddler で確認すると HTTPステータスコードで 403 が返っていることが確認できます。

    f:id:ksby:20160207024313p:plain

  4. Ctrl+F2 を押して Tomcat を停止します。

  5. 一旦 commit します。

次回は。。。

テストを作成します。

ソースコード

messages_ja_JP.properties

ConfirmresultParamForm.lendingAppId.emptyerr=貸出申請IDが指定されていません。
ConfirmresultForm.lendingApp.nodataerr=指定された貸出申請IDでは貸出承認されておりません。
Confirmresult.lendingUserId.notequalerr=申請者以外のユーザのため閲覧できません。
  • Confirmresult.lendingUserId.notequalerr を追加します。

ConfirmresultForm.java

package ksbysample.webapp.lending.web.confirmresult;

import ksbysample.webapp.lending.entity.LendingApp;
import ksbysample.webapp.lending.entity.LendingBook;
import lombok.Data;
import lombok.NoArgsConstructor;

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

@Data
@NoArgsConstructor
public class ConfirmresultForm {

    private LendingApp lendingApp;

    private Long lendingUserId;

    private String lendingUserName;

    private String approvalUserName;

    private List<ApprovedBookForm> approvedBookFormList;

    public void setApprovedBookFormListFromLendingBookList(List<LendingBook> lendingBookList) {
        this.approvedBookFormList = null;
        if (lendingBookList != null) {
            this.approvedBookFormList = lendingBookList.stream()
                    .map(ApprovedBookForm::new)
                    .collect(Collectors.toList());
        }
    }

}
  • private Long lendingUserId; を追加します。

ConfirmresultService.java

package ksbysample.webapp.lending.web.confirmresult;

import ksbysample.webapp.lending.dao.LendingAppDao;
import ksbysample.webapp.lending.dao.LendingBookDao;
import ksbysample.webapp.lending.dao.UserInfoDao;
import ksbysample.webapp.lending.entity.LendingApp;
import ksbysample.webapp.lending.entity.LendingBook;
import ksbysample.webapp.lending.entity.UserInfo;
import ksbysample.webapp.lending.helper.download.booklistcsv.BookListCsvData;
import ksbysample.webapp.lending.helper.download.booklistcsv.BookListCsvDataConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;

import static ksbysample.webapp.lending.values.LendingAppStatusValues.APPLOVED;
import static ksbysample.webapp.lending.values.LendingBookLendingAppFlgValues.APPLY;

@Service
public class ConfirmresultService {

    @Autowired
    private LendingAppDao lendingAppDao;

    @Autowired
    private UserInfoDao userInfoDao;

    @Autowired
    private LendingBookDao lendingBookDao;

    @Autowired
    private BookListCsvDataConverter bookListCsvDataConverter;

    public void setDispData(Long lendingAppId, ConfirmresultForm confirmresultForm) {
        LendingApp lendingApp = lendingAppDao.selectByIdAndStatus(lendingAppId, Arrays.asList(APPLOVED.getValue()));
        UserInfo lendingUserInfo = null;
        UserInfo approvalUserInfo = null;
        if (lendingApp != null) {
            lendingUserInfo = userInfoDao.selectById(lendingApp.getLendingUserId());
            approvalUserInfo = userInfoDao.selectById(lendingApp.getApprovalUserId());
        }
        List<LendingBook> lendingBookList
                = lendingBookDao.selectByLendingAppIdAndLendingAppFlg(lendingAppId, APPLY.getValue());

        confirmresultForm.setLendingApp(lendingApp);
        if (lendingUserInfo != null) {
            confirmresultForm.setLendingUserId(lendingUserInfo.getUserId());
            confirmresultForm.setLendingUserName(lendingUserInfo.getUsername());
        }
        if (approvalUserInfo != null) {
            confirmresultForm.setApprovalUserName(approvalUserInfo.getUsername());
        }
        confirmresultForm.setApprovedBookFormListFromLendingBookList(lendingBookList);
    }

    public List<BookListCsvData> getDownloadData(Long lendingAppId) {
        List<LendingBook> lendingBookList
                = lendingBookDao.selectByLendingAppIdAndLendingAppFlg(lendingAppId, APPLY.getValue());
        List<BookListCsvData> bookListCsvDataList = bookListCsvDataConverter.convertFrom(lendingBookList);
        return bookListCsvDataList;
    }

}
  • setDispData メソッド内で String の lendingUserName, approvalUserName にユーザ名を取得していたのを UserInfo クラスの lendingUserInfo, approvalUserInfo にデータを取得して、そこからユーザID、ユーザ名をコピーするようにします。

ConfirmresultController.java

package ksbysample.webapp.lending.web.confirmresult;

import ksbysample.webapp.lending.exception.WebApplicationRuntimeException;
import ksbysample.webapp.lending.helper.download.DataDownloadHelper;
import ksbysample.webapp.lending.helper.download.booklistcsv.BookListCsvData;
import ksbysample.webapp.lending.helper.download.booklistcsv.BookListCsvDownloadHelper;
import ksbysample.webapp.lending.helper.message.MessagesPropertiesHelper;
import ksbysample.webapp.lending.security.LendingUserDetailsHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

@Controller
@RequestMapping("/confirmresult")
public class ConfirmresultController {

    @Autowired
    private MessagesPropertiesHelper messagesPropertiesHelper;

    @Autowired
    private ConfirmresultService confirmresultService;

    @RequestMapping
    public String index(@Validated ConfirmresultParamForm confirmresultParamForm
            , BindingResult bindingResult
            , ConfirmresultForm confirmresultForm
            , BindingResult bindingResultOfConfirmresultForm
            , HttpServletResponse response) {
        if (bindingResult.hasErrors()) {
            throw new WebApplicationRuntimeException(
                    messagesPropertiesHelper.getMessage("ConfirmresultParamForm.lendingAppId.emptyerr", null));
        }

        // 画面に表示するデータを取得する
        confirmresultService.setDispData(confirmresultParamForm.getLendingAppId(), confirmresultForm);

        // 指定された貸出申請IDで承認済のデータがない場合には、貸出申請結果確認画面上にエラーメッセージを表示する
        if (confirmresultForm.getLendingApp() == null) {
            bindingResultOfConfirmresultForm.reject("ConfirmresultForm.lendingApp.nodataerr");
        }
        else {
            // 指定された貸出申請IDの申請者とログインしているユーザが一致しない場合にはエラーメッセージを表示し、
            // HTTP ステータスコードも 403 を返す
            if (!Objects.equals(confirmresultForm.getLendingUserId(), LendingUserDetailsHelper.getLoginUserId())) {
                response.setStatus(HttpStatus.FORBIDDEN.value());
                throw new WebApplicationRuntimeException(
                        messagesPropertiesHelper.getMessage("Confirmresult.lendingUserId.notequalerr", null));
            }
        }

        return "confirmresult/confirmresult";
    }

    @RequestMapping(value = "/filedownloadByResponse", method = RequestMethod.POST)
    public void filedownloadByResponse(ConfirmresultForm confirmresultForm
            , BindingResult bindingResult
            , HttpServletResponse response) throws IOException {

        ..........
    }

    ..........

}
  • index メソッドの以下の点を変更します。
    • 引数に HttpServletResponse response を追加します。
    • if (!Objects.equals(confirmresultForm.getLendingUserId(), LendingUserDetailsHelper.getLoginUserId())) { ... } の処理を追加します。403 を返すために response.setStatus を呼び出し、WebApplicationRuntimeException を throw して共通エラー画面が表示されるようにします。
  • 今回の主題とは直接関係ありませんが、filedownloadByResponse メソッドの引数 @Validated ConfirmresultForm confirmresultForm から @Validated を削除します。ConfirmresultForm クラス内には Bean Validation のアノテーションを付加していないので不要なためです。

履歴

2016/02/07
初版発行。