#ifndef _diffusion_authentication_control_h_
#define _diffusion_authentication_control_h_ 1

/*
 * Copyright © 2014 - 2025 DiffusionData Ltd., All Rights Reserved.
 *
 * Use is subject to licence terms.
 *
 * NOTICE: All information contained herein is, and remains the
 * property of DiffusionData. The intellectual and technical
 * concepts contained herein are proprietary to DiffusionData and
 * may be covered by U.S. and Foreign Patents, patents in process, and
 * are protected by trade secret or copyright law.
 */

/**
 * @file authentication-control.h
 *
 * Allows a client session to authenticate the credentials of other
 * sessions, and optionally revoke such authentications.
 *
 * Sessions are authenticated by a chain of authenticators. A client session can
 * participate in the authentication process by creating an authenticator and
 * registering it with the server.
 *
 * Each authenticator is registered under a particular authenticator name. For
 * registration to succeed, the server's security configuration must include a
 * matching {@code control-authentication-handler} entry for the name, otherwise
 * registration will fail and the authenticator will be closed immediately.
 *
 * Each client session can register a single authenticator for a given
 * authenticator name.
 *
 * For each authentication event, the server will use its configuration to
 * determine the authenticator priority order. The server may call
 * authenticators in serial or parallel. The server may stop the authentication
 * process as soon as it has an allow or deny response from an authenticator and
 * all higher priority authenticators have abstained.
 *
 * For a configured control authenticator, the server will select a single
 * authenticator from those registered for the authenticator name. If no
 * authenticators are currently registered, the server will consult the next
 * configured authenticator in priority order.
 *
 * ### Access control
 *
 * In order to register an authenticator a session needs both
 * `REGISTER_HANDLER REGISTER_HANDLER` and `AUTHENTICATE` permissions.
 *
 * In order to revoke a session's authentication a session needs both
 * `MODIFY_SESSION` and `AUTHENTICATE` permissions.
 */

#include "authenticator.h"
#include "hash.h"
#include "registration.h"
#include "session.h"
#include "types/client_details_types.h"

/**
 * If not specified, the group name "default" is used when registering
 * authentication handlers.
 */
#define DEFAULT_AUTH_GROUP_NAME "default"

/**
 * @brief Callback when an authentication handler is active.
 *
 * @param session            The currently active session.
 * @param registered_handler The registered handler
 *
 * @return HANDLER_SUCCESS or HANDLER_FAILURE.
 */
typedef int (*authenticator_on_active)(SESSION_T *session, const DIFFUSION_REGISTRATION_T *registered_handler);

/**
 * @brief Callback when an authentication handler has received a connection request to be
 * authenticated.
 *
 * @param session                     The currently active session.
 * @param principal                   The principal of the connection request to be authenticated
 * @param credentials                 The credentials of the connection request to be authenticated
 * @param session_properties          The session properties of the connection request to be authenticated
 * @param proposed_session_properties The proposed properties from the connection request to be authenticated
 * @param authenticator               The authenticator. Used to authenticate connection requests (see authenticator.h)
 *
 * @return HANDLER_SUCCESS or HANDLER_FAILURE.
 */
typedef int (*authenticator_on_authenticate)(
    SESSION_T *session,
    const char *principal,
    const CREDENTIALS_T *credentials,
    const HASH_T *session_properties,
    const HASH_T *proposed_session_properties,
    const DIFFUSION_AUTHENTICATOR_T *authenticator);

/**
 * @brief Callback when an authenticator has encountered an error.
 *
 * @param error The received error.
 *
 * @return HANDLER_SUCCESS or HANDLER_FAILURE.
 */
typedef int (*authenticator_on_error)(const DIFFUSION_ERROR_T *error);

/**
 * @brief Callback when an authentication handler is closed.
 */
typedef void (*authenticator_on_close)(void);

/**
 * @brief Structure supplied as part of a `diffusion_set_authentication_handler` request.
 */
typedef struct diffusion_authentication_handler_s
{
    ///  Name of the authentication handler.
    char *handler_name;
    /// Callback when the authentication handler is
    /// active.
    authenticator_on_active on_active;
    /// Callback when a connection request to be
    /// authenticated has been received.
    authenticator_on_authenticate on_authenticate;
    /// Callback when the authentication handler
    /// encounters an error.
    authenticator_on_error on_error;
    /// Callback when an authentication handler
    /// is closed.
    authenticator_on_close on_close;
} DIFFUSION_AUTHENTICATION_HANDLER_T;

/**
 * @brief Structure supplied when issuing an `diffusion_set_authentication_handler` request.
 */
typedef struct diffusion_authentication_handler_params_s
{
    /// Handler
    DIFFUSION_AUTHENTICATION_HANDLER_T *handler;
    /// Standard service error handler callback.
    ERROR_HANDLER_T on_error;
    /// Standard conversation discard callback.
    DISCARD_HANDLER_T on_discard;
    /// User-supplied context to return to callbacks.
    void *context;
} DIFFUSION_AUTHENTICATION_HANDLER_PARAMS_T;

/**
 * @ingroup PublicAPI_AuthenticationControl
 *
 * @brief Register an authentication handler for client authentication events.
 *
 * @param session       The session handle. If NULL, this function returns immediately
 *                      with the value NULL.
 * @param params        Parameters defining the request to register an
 *                      authentication handler.
 */
void diffusion_set_authentication_handler(SESSION_T *session, const DIFFUSION_AUTHENTICATION_HANDLER_PARAMS_T params);



/**
 * @brief Callback for `diffusion_get_path_permissions`.
 *
 * @param session   The current active session.
 * @param context   User-supplied context from the originating call.
 *
 * @return HANDLER_SUCCESS or HANDLER_FAILURE.
 *
 * @since 6.12
 */
typedef int (*on_session_revoked_cb)(SESSION_T *session, void *context);


/**
 * @brief Structure supplied when issuing a `diffusion_revoke_authentication` request.
 *
 * @since 6.12
 */
typedef struct diffusion_revoke_authentication_params_s
{
    /// identifies the client session to revoke
    SESSION_ID_T *session_id;

    /// Callback
    on_session_revoked_cb on_session_authentication_revoked;

    /// Callback to handle errors. Can be NULL.
    ERROR_HANDLER_T on_error;

    /// Callback to handle discards. Can be NULL.
    DISCARD_HANDLER_T on_discard;

    /// User supplied context. Can be NULL.
    void *context;
} DIFFUSION_REVOKE_AUTHENTICATION_PARAMS_T;

/**
 * @ingroup PublicAPI_AuthenticationControl
 *
 * @brief Revokes a session's authentication.
 *
 * This will immediately close the specified client session.
 *
 * @param session       The session handle. If NULL, this function returns immediately.
 * @param params        Parameters describing the `diffusion_revoke_authentication`
 *                      request and callback handlers which may be invoked
 *                      in response.
 * @param api_error     Populated on API error. Can be NULL.
 *
 * @return true if the operation was successful. False, otherwise. In this case, if
 *         a non-NULL `api_error` pointer has been provided, this will be populated
 *         with the error information and should be freed with `diffusion_api_error_free`.
 *
 * @since 6.12
 */
bool diffusion_revoke_authentication(
    SESSION_T *session,
    const DIFFUSION_REVOKE_AUTHENTICATION_PARAMS_T params,
    DIFFUSION_API_ERROR *api_error);

#endif
