SDPepe/AppArt

View on GitHub
app/src/main/java/ch/epfl/sdp/appart/login/MockLoginService.java

Summary

Maintainability
A
0 mins
Test Coverage
A
93%
package ch.epfl.sdp.appart.login;


import androidx.core.util.Pair;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.CompletableFuture;

import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Singleton;

import ch.epfl.sdp.appart.login.exceptions.LoginServiceRequestFailedException;
import ch.epfl.sdp.appart.login.exceptions.MockLoginServiceException;
import ch.epfl.sdp.appart.user.AppUser;
import ch.epfl.sdp.appart.user.User;

@Singleton
public class MockLoginService implements LoginService {

    private final Map<Pair<String, String>, User> users = new HashMap<>();
    private User currentUser = null;

    @Inject
    public MockLoginService() {
        //using user id as password to make it straightforward
        AppUser antoine = new AppUser("1111", "antoine@epfl.ch");
        Pair<String, String> antoineEmailPassword = new Pair<>(antoine.getUserEmail(),
                antoine.getUserId());
        users.put(antoineEmailPassword, antoine);
        AppUser lorenzo = new AppUser("2222", "lorenzo@epfl.ch");
        Pair<String, String> lorenzoEmailPassword = new Pair<>(lorenzo.getUserEmail(),
                lorenzo.getUserId());
        users.put(lorenzoEmailPassword, lorenzo);
        AppUser carlo = new AppUser("3333", "carlo@epfl.ch");
        Pair<String, String> carloEmailPassword = new Pair<>(carlo.getUserEmail(),
                carlo.getUserId());
        users.put(carloEmailPassword, carlo);
        AppUser filippo = new AppUser("4444", "filippo@epfl.ch");
        Pair<String, String> filippoEmailPassword = new Pair<>(filippo.getUserEmail(),
                filippo.getUserId());
        users.put(filippoEmailPassword, filippo);
        AppUser emilien = new AppUser("5555", "emilien@epfl.ch");
        Pair<String, String> emilienEmailPassword = new Pair<>(emilien.getUserEmail(),
                emilien.getUserId());
        users.put(emilienEmailPassword, emilien);
        AppUser quentin = new AppUser("6666", "quentin@epfl.ch");
        Pair<String, String> quentinEmailPassword = new Pair<>(quentin.getUserEmail(),
                quentin.getUserId());
        users.put(quentinEmailPassword, quentin);
        AppUser testUser = new AppUser("password", "test@testappart.ch");
        Pair<String, String> testUserEmailPassword = new Pair<>(testUser.getUserEmail(),
                testUser.getUserId());
        users.put(testUserEmailPassword, testUser);
        lorenzo.setName("Lorenzo");
        lorenzo.setPhoneNumber("000");
        lorenzo.addAdId("id0");
    }

    /**
     * Finds the user that has the specified email and password
     *
     * @param email    the email of the user
     * @param password the password of the user
     * @return a valid user if a matching user is found, null otherwise
     */
    @Nullable
    private User findMatchingUserWithPasswordAndEmail(String email, String password) {
        User result = null;
        for (Map.Entry<Pair<String, String>, User> entry : users.entrySet()) {
            String entryEmail = entry.getKey().first;
            String entryPassword = entry.getKey().second;
            if (email.equals(entryEmail) && password.equals(entryPassword)) {
                result = entry.getValue();
            }
        }
        return result;
    }

    @Override
    public CompletableFuture<User> loginWithEmail(String email, String password) {
        if (email == null) throw new IllegalArgumentException("Email cannot be null !");
        if (password == null) throw new IllegalArgumentException("Password cannot be null !");

        currentUser = findMatchingUserWithPasswordAndEmail(email, password);
        CompletableFuture<User> result = new CompletableFuture<>();
        if (currentUser == null) {
            result.completeExceptionally(new LoginServiceRequestFailedException("Failed to login " +
                    "the user !"));
        } else {
            result.complete(currentUser);
        }

        return result;
    }

    @Override
    public User getCurrentUser() {
        return currentUser;
    }

    @Override
    public CompletableFuture<Void> resetPasswordWithEmail(String email) {
        CompletableFuture<Void> result = new CompletableFuture<>();
        for (Map.Entry<Pair<String, String>, User> entry : users.entrySet()) {
            String entryEmail = entry.getKey().first;
            if (email.equals(entryEmail)) {
                result.complete(null);
                return result;
            }
        }
        result.completeExceptionally(new LoginServiceRequestFailedException("Failed to find the " +
                "associated email !"));
        return result;
    }

    @Override
    public CompletableFuture<User> createUser(String email, String password) {
        if (email == null || password == null)
            throw new IllegalArgumentException("Arguments cannot be null !");
        if (currentUser != null)
            throw new IllegalStateException("The current user cannot be set !");

        CompletableFuture<User> result = new CompletableFuture<>();
        byte[] temporary = new byte[5]; //one more than the other to avoid collision
        new Random().nextBytes(temporary);
        String id = "1234";

        User newUser = new AppUser(id, email);
        users.put(new Pair<>(email, password), newUser);

        loginWithEmail(email, password)
                .thenApply(r -> result.complete(newUser))
                .exceptionally(result::completeExceptionally);

        return result;
    }


    @Override
    public CompletableFuture<Void> updateEmailAddress(String email) {
        if (email == null) throw new IllegalArgumentException("Email cannot be null !");
        if (getCurrentUser() == null) throw new IllegalStateException("Current user must be set !");
        CompletableFuture<Void> result = new CompletableFuture<>();

        for (Map.Entry<Pair<String, String>, User> entry : users.entrySet()) {
            if (entry.getValue().equals(currentUser)) {
                users.remove(entry.getKey()); //remove the old mapping
                users.put(new Pair<>(email, entry.getKey().second), currentUser); //refresh the
                // new mapping
                currentUser.setUserEmail(email);
                result.complete(null);
                return result;
            }
        }
        result.completeExceptionally(new MockLoginServiceException("Failed to retrieve the main " +
                "user in the mock login service !"));
        return result;
    }

    @Override
    public CompletableFuture<Void> updatePassword(String password) {
        if (password == null) throw new IllegalArgumentException("Password cannot be null !");
        if (getCurrentUser() == null) throw new IllegalStateException("Current user must be set !");
        CompletableFuture<Void> result = new CompletableFuture<>();

        for (Map.Entry<Pair<String, String>, User> entry : users.entrySet()) {
            if (entry.getValue().equals(currentUser)) {
                users.remove(entry.getKey()); //remove the old mapping
                users.put(new Pair<>(currentUser.getUserEmail(), password), currentUser);
                //refresh the new mapping
                result.complete(null);
                return result;
            }
        }
        result.completeExceptionally(new MockLoginServiceException("Failed to retrieve the main " +
                "user in the mock login service !"));
        return result;
    }

    @Override
    public CompletableFuture<Void> sendEmailVerification() {
        if (getCurrentUser() == null)
            throw new IllegalStateException("Current user must be set when sending verification " +
                    "mail !");
        CompletableFuture<Void> result = new CompletableFuture<>();
        result.complete(null);
        return result;
    }

    @Override
    public CompletableFuture<Void> deleteUser() {
        if (currentUser == null)
            throw new IllegalStateException("Current user must be set when deleting it !");
        CompletableFuture<Void> result = new CompletableFuture<>();

        Pair<String, String> keyToRemove = null;
        for (Map.Entry<Pair<String, String>, User> entry : users.entrySet()) {
            if (entry.getValue().equals(currentUser)) {
                keyToRemove = entry.getKey();
            }
        }

        if (keyToRemove != null) {
            users.remove(keyToRemove);
        }

        currentUser = null;
        result.complete(null);

        return result;
    }

    @Override
    public CompletableFuture<Void> reAuthenticateUser(String email, String password) {
        if (email == null) throw new IllegalArgumentException("Password cannot be null !");
        if (password == null) throw new IllegalArgumentException("Password cannot be null !");
        if (getCurrentUser() == null)
            throw new IllegalStateException("Current user must be set when reAuthentication !");

        //note : this function will never fail beyond this point
        CompletableFuture<Void> result = new CompletableFuture<>();
        result.complete(null);

        return result;
    }

    @Override
    public void signOut() {
        currentUser = null;
    }

    @Override
    public CompletableFuture<User> signInAnonymously() {
        User anonymousUser = new AppUser("anonymousUser", "anonymous@testappart.ch");
        CompletableFuture<User> futureAnonymous = new CompletableFuture<>();
        futureAnonymous.complete(anonymousUser);
        currentUser = anonymousUser;
        return futureAnonymous;
    }


}