package jenkins.security;

import hudson.Extension;
import hudson.model.User;
import org.acegisecurity.Authentication;
import org.acegisecurity.userdetails.UsernameNotFoundException;
import org.springframework.dao.DataAccessException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.logging.Logger;

import static java.util.logging.Level.*;

/**
 * Checks if the password given in the BASIC header matches the user's API token.
 *
 * @author Kohsuke Kawaguchi
 * @since 1.576
 */
@Extension
public class BasicHeaderApiTokenAuthenticator extends BasicHeaderAuthenticator {
    @Override
    public Authentication authenticate(HttpServletRequest req, HttpServletResponse rsp, String username, String password) throws ServletException {
        // attempt to authenticate as API token
        User u = User.getById(username, true);
        ApiTokenProperty t = u.getProperty(ApiTokenProperty.class);
        if (t!=null && t.matchesPassword(password)) {
            try {
                return u.impersonate();
            } catch (UsernameNotFoundException x) {
                // The token was valid, but the impersonation failed. This token is clearly not his real password,
                // so there's no point in continuing the request processing. Report this error and abort.
                LOGGER.log(WARNING, "API token matched for user "+username+" but the impersonation failed",x);
                throw new ServletException(x);
            } catch (DataAccessException x) {
                throw new ServletException(x);
            }
        }
        return null;
    }

    private static final Logger LOGGER = Logger.getLogger(BasicHeaderApiTokenAuthenticator.class.getName());
}
