package com.github.kazuki43zoo.app.account;
import com.github.kazuki43zoo.core.message.Message;
import com.github.kazuki43zoo.domain.model.account.Account;
import com.github.kazuki43zoo.domain.model.account.AccountAuthority;
import com.github.kazuki43zoo.domain.repository.account.AccountsSearchCriteria;
import com.github.kazuki43zoo.domain.service.account.AccountService;
import org.dozer.Mapper;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.terasoluna.gfw.common.exception.BusinessException;
import org.terasoluna.gfw.web.token.transaction.TransactionTokenCheck;
import org.terasoluna.gfw.web.token.transaction.TransactionTokenType;
import javax.inject.Inject;
@TransactionTokenCheck("accounts")
@RequestMapping("accounts")
@Controller
public class AccountsController {
@Inject
Mapper beanMapper;
@Inject
AccountService accountService;
@RequestMapping(method = RequestMethod.GET)
public String list(final @Validated AccountsSearchQuery query, final BindingResult bindingResult, final @PageableDefault(size = 15) Pageable pageable, final Model model) {
if (bindingResult.hasErrors()) {
return "account/list";
}
final AccountsSearchCriteria criteria = beanMapper.map(query, AccountsSearchCriteria.class);
final Page<Account> page = accountService.searchAccounts(criteria, pageable);
model.addAttribute("page", page);
return "account/list";
}
@TransactionTokenCheck(type = TransactionTokenType.BEGIN)
@RequestMapping(path = "{accountUuid}", method = RequestMethod.GET)
public String show(final @PathVariable("accountUuid") String accountUuid, final Model model) {
final Account account = accountService.getAccount(accountUuid);
model.addAttribute(account);
return "account/detail";
}
@TransactionTokenCheck(value = "create", type = TransactionTokenType.BEGIN)
@RequestMapping(method = RequestMethod.GET, params = "form=create")
public String createForm(final AccountForm form) {
return "account/createForm";
}
@TransactionTokenCheck(value = "create")
@RequestMapping(method = RequestMethod.POST)
public String create(final @Validated AccountForm form, final BindingResult bindingResult, final Model model, final RedirectAttributes redirectAttributes) {
if (bindingResult.hasErrors()) {
return createForm(form);
}
final Account inputAccount = beanMapper.map(form, Account.class);
for (final String authority : form.getAuthorities()) {
inputAccount.addAuthority(new AccountAuthority(null, authority));
}
final Account createdAccount;
try {
createdAccount = accountService.create(inputAccount);
} catch (final DuplicateKeyException e) {
model.addAttribute(Message.ACCOUNT_ID_USED.resultMessages());
return createForm(form);
} catch (final BusinessException e) {
model.addAttribute(e.getResultMessages());
return createForm(form);
}
return redirectDetailView(createdAccount.getAccountUuid(), Message.ACCOUNT_CREATED, redirectAttributes);
}
@TransactionTokenCheck(value = "edit", type = TransactionTokenType.BEGIN)
@RequestMapping(path = "{accountUuid}", method = RequestMethod.GET, params = "form=edit")
public String editForm(final @PathVariable("accountUuid") String accountUuid, final AccountForm form, final Model model) {
final Account account = accountService.getAccount(accountUuid);
model.addAttribute(account);
beanMapper.map(account, form);
for (final AccountAuthority accountAuthority : account.getAuthorities()) {
form.addAuthority(accountAuthority.getAuthority());
}
form.setPassword(null);
return "account/editForm";
}
@TransactionTokenCheck(value = "edit")
@RequestMapping(path = "{accountUuid}", method = RequestMethod.POST, params = "_method=put")
public String edit(final @PathVariable("accountUuid") String accountUuid, final @Validated AccountForm form, final BindingResult bindingResult, final Model model, final RedirectAttributes redirectAttributes) {
if (bindingResult.hasErrors()) {
return editRedo(accountUuid, model);
}
final Account inputAccount = beanMapper.map(form, Account.class);
inputAccount.setAccountUuid(accountUuid);
for (final String authority : form.getAuthorities()) {
inputAccount.addAuthority(new AccountAuthority(accountUuid, authority));
}
try {
accountService.change(inputAccount);
} catch (final DuplicateKeyException e) {
model.addAttribute(Message.ACCOUNT_ID_USED.resultMessages());
return editRedo(accountUuid, model);
} catch (final BusinessException e) {
model.addAttribute(e.getResultMessages());
return editRedo(accountUuid, model);
}
return redirectDetailView(accountUuid, Message.ACCOUNT_EDITED, redirectAttributes);
}
@TransactionTokenCheck
@RequestMapping(path = "{accountUuid}", method = RequestMethod.POST, params = "_method=delete")
public String delete(final @PathVariable("accountUuid") String accountUuid, final RedirectAttributes redirectAttributes) {
accountService.delete(accountUuid);
redirectAttributes.addFlashAttribute(Message.ACCOUNT_DELETED.resultMessages());
return "redirect:/app/accounts";
}
@TransactionTokenCheck
@RequestMapping(path = "{accountUuid}/unlock", method = RequestMethod.POST, params = "_method=patch")
public String unlock(final @PathVariable("accountUuid") String accountUuid, final RedirectAttributes redirectAttributes) {
accountService.unlock(accountUuid);
return redirectDetailView(accountUuid, Message.ACCOUNT_UNLOCKED, redirectAttributes);
}
private String editRedo(final String accountUuid, final Model model) {
final Account account = accountService.getAccount(accountUuid);
model.addAttribute(account);
return "account/editForm";
}
private String redirectDetailView(final String accountUuid, final Message message, final RedirectAttributes redirectAttributes) {
redirectAttributes.addFlashAttribute(message.resultMessages());
redirectAttributes.addAttribute("accountUuid", accountUuid);
return "redirect:/app/accounts/{accountUuid}";
}
}