Commit 769ada5a authored by Tomas Madeja's avatar Tomas Madeja
Browse files

feat: authenticate an existing user

parent d9b887a6
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -3,10 +3,29 @@ package cz.muni.fi.pa165.icehockeymanager.dao;
import cz.muni.fi.pa165.icehockeymanager.model.User;
import org.springframework.stereotype.Repository;

import javax.persistence.NoResultException;
import java.util.Optional;

@Repository
public class UserAuthDao extends AbstractDao<User>{

    public UserAuthDao() {
        super(User.class);
    }

    public Optional<User> findByUsername(String username) {
        User user = null;
        try {
            user = (User) entityManager
                    .createNativeQuery(
                            "SELECT u FROM User u WHERE u.username = :username",
                            User.class
                    )
                    .setParameter("username", username)
                    .getSingleResult();
        } catch (NoResultException ignored) {

        }
        return Optional.ofNullable(user);
    }
}
+8 −0
Original line number Diff line number Diff line
package cz.muni.fi.pa165.icehockeymanager.services;

public interface UserAuthService {

    /**
     * Authenticate user
     * @param username username
     * @param password plaintext password
     * @return true if the password is correct, else false
     */
    boolean authenticateUser(String username, String password);
}
+25 −1
Original line number Diff line number Diff line
package cz.muni.fi.pa165.icehockeymanager.services;

import cz.muni.fi.pa165.icehockeymanager.dao.UserAuthDao;
import cz.muni.fi.pa165.icehockeymanager.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;

@Service
public class UserAuthServiceImpl implements UserAuthService{

    public final Argon2Service argonEncoder;
    public final UserAuthDao userAuthDao;


    @Autowired
    public UserAuthServiceImpl(Argon2Service argonEncoder) {
    public UserAuthServiceImpl(
            Argon2Service argonEncoder,
            UserAuthDao userAuthDao
    ) {
        this.argonEncoder = argonEncoder;
        this.userAuthDao = userAuthDao;
    }

    public boolean authenticateUser(String username, String password) {
        Optional<User> userOpt = userAuthDao.findByUsername(username);

        AtomicBoolean isCorrectPassword = new AtomicBoolean(false);
        userOpt.ifPresent(user -> {
            isCorrectPassword.set(
                    argonEncoder.compare(password, user.getPassword())
            );
        });

        return isCorrectPassword.get();
    }
}
+69 −0
Original line number Diff line number Diff line
package cz.muni.fi.pa165.icehockeymanager.services;

import cz.muni.fi.pa165.icehockeymanager.config.ApplicationConfig;
import cz.muni.fi.pa165.icehockeymanager.dao.UserAuthDao;
import cz.muni.fi.pa165.icehockeymanager.model.User;
import org.assertj.core.api.SoftAssertions;
import org.assertj.core.api.junit.jupiter.InjectSoftAssertions;
import org.assertj.core.api.junit.jupiter.SoftAssertionsExtension;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;

import java.util.Optional;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;


@ExtendWith(SpringExtension.class)
@ExtendWith(SoftAssertionsExtension.class)
@ContextConfiguration(classes = ApplicationConfig.class)
class UserAuthServiceImplTest {

    public static final String CORRECT_USERNAME = "ivan";
    public static final String INCORRECT_USERNAME = "gzegorz";

    public static final String CORRECT_PASSWORD = "correct";
    public static final String INCORRECT_PASSWORD = "incorrect";

    private UserAuthService authService;

    @InjectSoftAssertions
    private SoftAssertions softly;

    @Autowired
    private Argon2Service argonEncoder;

    private UserAuthDao userAuthDaoMock;

    @BeforeEach
    public void setUp() {
        userAuthDaoMock = mock(UserAuthDao.class);
        authService = new UserAuthServiceImpl(argonEncoder, userAuthDaoMock);
    }

    @Test
    public void authenticateCorrectPassword() {
        String password = argonEncoder.encodePassword(CORRECT_PASSWORD);
        var user = buildUser(1L, CORRECT_USERNAME, password);

        when(userAuthDaoMock.findByUsername(CORRECT_USERNAME))
                .thenReturn(Optional.of(user));

        softly.assertThat(
                authService.authenticateUser(CORRECT_USERNAME, CORRECT_PASSWORD)
        ).isTrue();
    }

    private static User buildUser(Long id, String username, String passwordHash) {
        var user = new User();
        user.setId(id);
        user.setUsername(username);
        user.setPassword(passwordHash);
        return user;
    }
}
 No newline at end of file