org.jbb.members.web.base.controller.UcpEditAccountController.java Source code

Java tutorial

Introduction

Here is the source code for org.jbb.members.web.base.controller.UcpEditAccountController.java

Source

/*
 * Copyright (C) 2018 the original author or authors.
 *
 * This file is part of jBB Application Project.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  You may obtain a copy of the License at
 *        http://www.apache.org/licenses/LICENSE-2.0
 */

package org.jbb.members.web.base.controller;

import static org.jbb.permissions.api.permission.domain.MemberPermissions.CAN_CHANGE_EMAIL;

import java.util.Optional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jbb.lib.commons.vo.Email;
import org.jbb.lib.commons.vo.Password;
import org.jbb.lib.commons.vo.Username;
import org.jbb.members.api.base.AccountDataToChange;
import org.jbb.members.api.base.AccountException;
import org.jbb.members.api.base.Member;
import org.jbb.members.api.base.MemberService;
import org.jbb.members.web.base.form.EditAccountForm;
import org.jbb.members.web.base.logic.EditAccountErrorsBindingMapper;
import org.jbb.permissions.api.PermissionService;
import org.jbb.security.api.password.PasswordService;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Slf4j
@Controller
@RequiredArgsConstructor
@RequestMapping(value = "/ucp/profile/editAccount")
public class UcpEditAccountController {
    private static final String VIEW_NAME = "ucp/profile/editAccount";
    private static final String EDIT_ACCOUNT_FORM = "editAccountForm";
    private static final String FORM_SAVED_FLAG = "editAccountFormSaved";
    private static final String EMAIL_FIELD_ENABLED = "hasChangeEmailPermission";

    private final MemberService memberService;
    private final PasswordService passwordService;
    private final PermissionService permissionService;
    private final EditAccountErrorsBindingMapper errorsBindingMapper;

    private static void fillFieldWithUsername(EditAccountForm editAccountForm, Member member) {
        editAccountForm.setUsername(member.getUsername().toString());
    }

    private static boolean passwordChanged(EditAccountForm editAccountForm) {
        return StringUtils.isNotEmpty(editAccountForm.getNewPassword())
                || StringUtils.isNotEmpty(editAccountForm.getNewPasswordAgain());
    }

    private String formViewWithError(Model model) {
        model.addAttribute(FORM_SAVED_FLAG, false);
        model.addAttribute(EMAIL_FIELD_ENABLED, permissionService.checkPermission(CAN_CHANGE_EMAIL));
        return VIEW_NAME;
    }

    private boolean emailChanged(Member member, Email newEmail) {
        boolean changed = !member.getEmail().equals(newEmail);
        if (changed) {
            permissionService.assertPermission(CAN_CHANGE_EMAIL);
        }
        return changed;
    }

    @RequestMapping(method = RequestMethod.GET)
    public String editAccount(Model model, Authentication authentication,
            @ModelAttribute(EDIT_ACCOUNT_FORM) EditAccountForm form) {
        Member member = getCurrentMember(authentication);
        fillFieldWithUsername(form, member);

        if (!model.containsAttribute(FORM_SAVED_FLAG)) {
            form.setEmail(member.getEmail().toString());
            model.addAttribute(EDIT_ACCOUNT_FORM, form);
        }

        model.addAttribute(EMAIL_FIELD_ENABLED, permissionService.checkPermission(CAN_CHANGE_EMAIL));

        return VIEW_NAME;
    }

    @RequestMapping(method = RequestMethod.POST)
    public String editAccountPost(Model model, Authentication authentication,
            @ModelAttribute(EDIT_ACCOUNT_FORM) EditAccountForm form, BindingResult bindingResult) {
        Member member = getCurrentMember(authentication);
        fillFieldWithUsername(form, member);

        // check correction of current password - it is necessary to proceed
        if (currentPasswordIsIncorrect(member.getId(), form.getCurrentPassword())) {
            bindingResult.rejectValue("currentPassword", "CP", "Given password is not match to current password");
            return formViewWithError(model);
        }

        // detect which data user want to update
        AccountDataToChange accountData = AccountDataToChange.builder().build();
        Email newEmail = Email.builder().value(form.getEmail()).build();
        if (emailChanged(member, newEmail)) {
            accountData.setEmail(Optional.of(newEmail));
        }

        if (passwordChanged(form)) {
            Password newPassword = Password.builder().value(form.getNewPassword().toCharArray()).build();
            Password newPasswordAgain = Password.builder().value(form.getNewPasswordAgain().toCharArray()).build();
            if (newPassword.equals(newPasswordAgain)) {
                accountData.setNewPassword(Optional.of(newPassword));
            } else {
                bindingResult.rejectValue("newPassword", "NP", "Passwords don't match");
                return formViewWithError(model);
            }
        }

        // invoke service for updating data
        try {
            memberService.updateAccount(member.getId(), accountData);
        } catch (AccountException e) {
            log.debug("Problem with updating account for username {} with data to change: {}", member.getUsername(),
                    accountData, e);
            errorsBindingMapper.map(e.getConstraintViolations(), bindingResult);
            return formViewWithError(model);
        }

        model.addAttribute(FORM_SAVED_FLAG, true);
        model.addAttribute(EMAIL_FIELD_ENABLED, permissionService.checkPermission(CAN_CHANGE_EMAIL));
        return VIEW_NAME;
    }

    private Member getCurrentMember(Authentication authentication) {
        User currentUser = (User) authentication.getPrincipal();
        Optional<Member> member = memberService
                .getMemberWithUsername(Username.builder().value(currentUser.getUsername()).build());
        if (member.isPresent()) {
            return member.get();
        } else {
            throw new UsernameNotFoundException(
                    String.format("User with username '%s' not found", currentUser.getUsername()));
        }
    }

    private boolean currentPasswordIsIncorrect(Long memberId, String currentPassword) {
        return !passwordService.verifyFor(memberId,
                Password.builder().value(currentPassword.toCharArray()).build());
    }
}