package org.intellimate.server.queries;

import org.apache.commons.validator.routines.EmailValidator;
import org.intellimate.server.BadRequestException;
import org.intellimate.server.JWTHelper;
import org.intellimate.server.NotFoundException;
import org.intellimate.server.UnauthorizedException;
import org.intellimate.server.database.model.tables.records.UserRecord;
import org.intellimate.server.database.operations.IzouInstanceOperations;
import org.intellimate.server.database.operations.UserOperations;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.crypto.bcrypt.BCrypt;

import java.util.Objects;

/**
 * handles all the authentication requests
 * @author LeanderK
 * @version 1.0
 */
public class Authentication {
    private static final Logger logger = LoggerFactory.getLogger(Authentication.class);
    private final IzouInstanceOperations izouInstanceOperations;
    private final UserOperations userOperations;
    private final JWTHelper jwtHelper;

    public Authentication(IzouInstanceOperations izouInstanceOperations, UserOperations userOperations, JWTHelper jwtHelper) {
        this.izouInstanceOperations = izouInstanceOperations;
        this.userOperations = userOperations;
        this.jwtHelper = jwtHelper;
    }

    /**
     * handles the login request for the users
     * @param email the email
     * @param password the password
     * @return if valid an access jwt-token
     */
    public String login(String email, String password) {
        Objects.nonNull(email);
        Objects.nonNull(password);
        UserRecord user = userOperations.getUser(email)
                .orElseThrow(() -> new NotFoundException("no user found for email: " + email));
        boolean valid = BCrypt.checkpw(password, user.getPassword());
        if (valid) {
            return jwtHelper.generateUserAccessJWT(user.getIdUser());
        } else {
            throw new UnauthorizedException("wrong password for email: " + email);
        }
    }

    /**
     * adds an user to the database
     * @param username the chosen username, must be at least 4 characters long
     * @param email the email
     * @param password the chosen password, must be at least 4 characters long
     * @throws BadRequestException if one of the parameters is invalid
     */
    public void addUser(String username, String email, String password) {
        Objects.nonNull(username);
        Objects.nonNull(email);
        Objects.nonNull(password);
        if (username.length() < 4) {
            throw new BadRequestException("invalid username length, must be at least 4: " + username);
        }
        if (password.length() < 4) {
            throw new BadRequestException("invalid password length, must be at least 4");
        }
        if (!EmailValidator.getInstance(false).isValid(email)) {
            throw new BadRequestException("invalid email: " + email);
        }
        String hashpw = BCrypt.hashpw(password, BCrypt.gensalt());
        UserRecord userRecord = new UserRecord(null, email, hashpw, username);
        userOperations.insertUser(userRecord);
    }

    /**
     * handles the refresh requests from the izou-instances
     * @param id the id of the izou-instance from the refresh-token
     * @return if valid an access jwt-token
     */
    public String refresh(String id) {
        try {
            int parsedID = Integer.parseInt(id);
            boolean valid = izouInstanceOperations.validateIzouInstanceID(parsedID);
            if (valid) {
                return jwtHelper.generateIzouAccessJWT(parsedID);
            } else {
                logger.info("invalid izou id", id);
                throw new UnauthorizedException("Invalid JWT, the registered instance was removed");
            }
        } catch (NumberFormatException e) {
            logger.info("unable to parse {} as an integer", id);
            throw new UnauthorizedException("Invalid JWT");
        }
    }
}

@@ -176,16 +176,20 @@
 .server.
+jwt.
 JWTHelpe
@@ -2016,1127 +2016,8 @@
  %7D%0A%0A
-    /**%0A     * adds an user to the database%0A     * @param username the chosen username, must be at least 4 characters long%0A     * @param email the email%0A     * @param password the chosen password, must be at least 4 characters long%0A     * @throws BadRequestException if one of the parameters is invalid%0A     */%0A    public void addUser(String username, String email, String password) %7B%0A        Objects.nonNull(username);%0A        Objects.nonNull(email);%0A        Objects.nonNull(password);%0A        if (username.length() %3C 4) %7B%0A            throw new BadRequestException(%22invalid username length, must be at least 4: %22 + username);%0A        %7D%0A        if (password.length() %3C 4) %7B%0A            throw new BadRequestException(%22invalid password length, must be at least 4%22);%0A        %7D%0A        if (!EmailValidator.getInstance(false).isValid(email)) %7B%0A            throw new BadRequestException(%22invalid email: %22 + email);%0A        %7D%0A        String hashpw = BCrypt.hashpw(password, BCrypt.gensalt());%0A        UserRecord userRecord = new UserRecord(null, email, hashpw, username);%0A        userOperations.insertUser(userRecord);%0A    %7D%0A%0A
     
@@ -2226,22 +2226,19 @@
 refresh(
-Str
 in
-g
+t
  id) %7B%0A 
@@ -2254,57 +2254,8 @@
 y %7B%0A
-            int parsedID = Integer.parseInt(id);%0A
     
@@ -2324,24 +2324,18 @@
 tanceID(
-parsedID
+id
 );%0A     
@@ -2413,16 +2413,10 @@
 JWT(
-parsedID
+id
 );%0A 

finished Authentication