package com.atlassian.stash.internal.spring.security;

import org.springframework.security.web.util.matcher.RequestMatcher;

import javax.servlet.http.HttpServletRequest;

import static com.atlassian.stash.internal.web.maintenance.MaintenanceController.PATH_LOCK;
import static com.atlassian.stash.internal.web.maintenance.MaintenanceController.PATH_MAINTENANCE;

/**
 * Matcher for {@link com.atlassian.stash.internal.web.maintenance.MaintenanceController maintenance} requests, used to
 * control which requests should be processed by Spring Security and which should not. This {@link RequestMatcher}
 * matches all maintenance related request that should not be secured because they need to be callable when the system
 * is in maintenance mode (and the database is potentially not latched/available):
 * <ul>
 *     <li>GET /mvc/maintenance - view maintenance status.</li>
 *     <li>POST /mvc/maintenance - submit a cancel token.</li>
 *     <li>GET /mvc/maintenance/lock - get lock status.</li>
 *     <li>DELETE /mvc/maintenance/lock - unlock the system.</li>
 * </ul>
 * <p>
 * Note that POST /mvc/maintenance/lock IS secured, since the system needs to be available for it to be lockable
 */
public class MaintenanceRequestMatcher implements RequestMatcher {

    private static final String PATH_MAINTENANCE_LOCK = PATH_MAINTENANCE + "/" + PATH_LOCK;

    @Override
    public boolean matches(HttpServletRequest request) {
        return "/mvc".equals(request.getServletPath()) &&
                (isMaintenance(request) || isUnlockMaintenance(request) || isViewLock(request));
    }

    private boolean isViewLock(HttpServletRequest request) {
        return "GET".equals(request.getMethod()) && PATH_MAINTENANCE_LOCK.equals(request.getPathInfo());
    }

    private boolean isMaintenance(HttpServletRequest request) {
        return PATH_MAINTENANCE.equals(request.getPathInfo());
    }

    private boolean isUnlockMaintenance(HttpServletRequest request) {
        return "DELETE".equals(request.getMethod()) && PATH_MAINTENANCE_LOCK.equals(request.getPathInfo());
    }
}
