package com.atlassian.bitbucket.mesh.auth;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import static com.atlassian.bitbucket.mesh.auth.ApplicationRole.*;
import static java.util.Objects.requireNonNull;

/**
 * @since 1.4
 */
public class DefaultAuthorisationManager implements AuthorisationManager {

    private final AuthenticationManager authenticationManager;

    public DefaultAuthorisationManager(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
    }

    @Override
    public void checkHasRole(@Nonnull ApplicationRole role, @Nullable String operationName) {
        if (!hasRole(requireNonNull(role, "role"))) {
            throw new AuthorisationException("Role '" + role + "' is required to access " +
                    (operationName == null ? "this service" : operationName));
        }
    }

    @Override
    public boolean hasRole(@Nonnull ApplicationRole role) {
        //If authenticationManager is null, authentication is disabled and this check should always pass
        return authenticationManager == null || authenticationManager.getPrincipal()
                .map(principal -> hasOrImpliesRole(principal, role))
                .orElse(false);
    }

    private static boolean hasOrImpliesRole(Principal principal, ApplicationRole role) {
        //The control plane can call any method
        ApplicationRole currentRole = principal.getRole();
        return currentRole == CONTROL_PLANE || currentRole == role;
    }
}
