package com.atlassian.bitbucket.permission;

import com.atlassian.bitbucket.AuthorisationException;
import com.atlassian.bitbucket.project.Project;
import com.atlassian.bitbucket.repository.Repository;
import com.atlassian.bitbucket.auth.AuthenticationContext;

import javax.annotation.Nonnull;

/**
 * A utility service for plugin developer to validate that the current user has a specific permission.
 * This service uses the {@link PermissionService} to check for a permission and will throw
 * {@link AuthorisationException} for any failed permission check.
 */
public interface PermissionValidationService {

    /**
     * Validate that the user is logged in
     *
     * @throws AuthorisationException if anonymous
     * @see AuthenticationContext#isAuthenticated()
     */
    void validateAuthenticated() throws AuthorisationException;

    /**
     * Validate that the current user has the specified global permission
     *
     * @param permission the requested permission. Must not be {@code null} and {@link Permission#isGlobal()}
     *                   must be true
     * @throws AuthorisationException if the current user is unauthorized
     * @see PermissionService#hasGlobalPermission(Permission)
     */
    void validateForGlobal(@Nonnull Permission permission) throws AuthorisationException;

    /**
     * Validate that the current user has the specified permission for the project
     *
     * @param project  the target project. Must not be {@code null}
     * @param permission the requested permission. Must not be {@code null} and {@link Permission#isGlobal()}
     *                   must be false
     * @throws AuthorisationException if the current user is unauthorized
     * @see PermissionService#hasProjectPermission(Project, Permission)
     */
    void validateForProject(@Nonnull Project project, @Nonnull Permission permission) throws AuthorisationException;

    /**
     * Validate that the current user has the specified permission for the project
     *
     * @param projectId  the ID of the target project
     * @param permission the requested permission. Must not be {@code null} and {@link Permission#isGlobal()}
     *                   must be false
     * @throws AuthorisationException if the current user is unauthorized
     * @see PermissionService#hasProjectPermission(Project, Permission)
     * @since 4.1
     */
    void validateForProject(int projectId, @Nonnull Permission permission);

    /**
     * Validate that the current user has the specified permission for the repository
     * <p>
     * Note that anonymous users accessing a public repository do not have the {@link Permission#REPO_READ}
     * permission. To perform read access validation that includes public repository access by anonymous users
     * see {@link #validateRepositoryAccessible(Repository)}.
     *
     * @param repository  the target repository. Must not be {@code null}
     * @param permission the requested permission. Must not be {@code null} and {@link Permission#isGlobal()}
     *                   must be false
     * @throws AuthorisationException if the current user is unauthorized
     * @see PermissionService#hasRepositoryPermission(Repository, Permission)
     */
    void validateForRepository(@Nonnull Repository repository, @Nonnull Permission permission) throws AuthorisationException;

    /**
     * Validate that the current user has the specified permission for the repository
     * <p>
     * Note that anonymous users accessing a public repository do not have the {@link Permission#REPO_READ}
     * permission. To perform read access validation that includes public repository access by anonymous users
     * see {@link #validateRepositoryAccessible(int)}.
     *
     * @param repositoryId  the ID of the target repository
     * @param permission the requested permission. Must not be {@code null} and {@link Permission#isGlobal()}
     *                   must be false
     * @throws AuthorisationException if the current user is unauthorized
     * @see PermissionService#hasRepositoryPermission(Repository, Permission)
     * @since 4.1
     */
    void validateForRepository(int repositoryId, @Nonnull Permission permission);

    /**
     * Validate that the current user (authenticated or not) has access to the given repository.
     * See {@link PermissionService#isRepositoryAccessible(Repository)} for a description of what
     * constitutes "access".
     *
     * @param repository the target repository. Must not be {@code null}
     * @throws AuthorisationException if the current user is unauthorized
     * @see PermissionService#isRepositoryAccessible(Repository)
     * @since 4.3
     */
    void validateRepositoryAccessible(@Nonnull Repository repository);

    /**
     * Validate that the current user (authenticated or not) has access to the given repository.
     * See {@link PermissionService#isRepositoryAccessible(int)} for a description of what constitutes
     * "access".
     *
     * @param repositoryId the ID of the target repository
     * @throws AuthorisationException if the current user is unauthorized
     * @see PermissionService#isRepositoryAccessible(int)
     * @since 4.3
     */
    void validateRepositoryAccessible(int repositoryId);
}
