import { Counter, EventWithContext } from "../core.js";
import { CoreModelDefinition } from "../models/coremodel.js";
import { Ident } from "../models/ident.js";
import { User } from "../models/user.js";
import { Service, ServiceParameters } from "../services/service.js";
import { Store } from "../stores/store.js";
import { OperationContext, WebContext } from "../utils/context.js";
import { HttpMethodType } from "../utils/httpcontext.js";
import CryptoService from "./cryptoservice.js";
import { Mailer } from "./mailer.js";
/**
 * Emitted when the /me route is called
 */
export interface EventAuthenticationGetMe extends EventWithContext {
    user: User;
}
/**
 * Emitted when new user registered
 */
export interface EventAuthenticationRegister extends EventAuthenticationGetMe {
    data: any;
    identId: string;
}
/**
 * Emitted when user logout
 */
export interface EventAuthenticationLogout extends EventWithContext {
}
/**
 * Sent when a user update his password
 */
export interface EventAuthenticationPasswordUpdate extends EventAuthenticationGetMe {
    password: string;
}
/**
 * Emitted when user login
 */
export interface EventAuthenticationLogin extends EventWithContext {
    userId: string;
    user?: User;
    identId: string;
    ident: Ident;
}
/**
 * Export when a user failed to authenticate with his password
 */
export interface EventAuthenticationLoginFailed extends EventAuthenticationGetMe {
}
/**
 * Implement a PasswordVerifier so you can implement
 * your own rules
 */
export interface PasswordVerifier extends Service {
    /**
     * If the password is not valid, send a 400 exception or
     * return false
     *
     * @param password to verify
     * @param user to verify from
     */
    validate(password: string, user?: User): Promise<boolean>;
}
/**
 * Information required to reset a password
 */
export interface PasswordRecoveryInfos {
    /**
     * Links are short lived
     */
    expire: number;
    /**
     * Generated token
     */
    token: string;
    /**
     * Login to reset password fors
     */
    login: string;
}
interface PasswordRecoveryBody extends PasswordRecoveryInfos {
    /**
     * Password to set
     */
    password: string;
}
/**
 * Login info
 *
 * If register = true, you can add many other information
 *
 * @SchemaAdditionalProperties
 */
interface LoginBody {
    login: string;
    register?: boolean;
    token?: string;
    email?: string;
    password?: string;
}
export declare class AuthenticationParameters extends ServiceParameters {
    /**
     * Idents store for authentication identifiers
     *
     * @default "Webda/Ident"
     */
    identModel?: string;
    /**
     * User store for authentication users
     *
     * @default "Webda/User"
     */
    userModel?: string;
    /**
     * @default "/auth"
     */
    url?: string;
    /**
     * Enable the email authentication
     */
    email?: {
        /**
         * Mailer service name
         */
        mailer?: string;
        /**
         * Allow user to create their account without validating their email first
         */
        postValidation: boolean;
        /**
         * Do not even validate the email at all
         */
        skipEmailValidation: boolean;
        /**
         * Minimal delay between two password recovery or validation email
         *
         * @default 3600000 * 4
         */
        delay: number;
        /**
         * When a delay is added between two attempt to authenticate
         *
         * @default 3
         */
        failedLoginBeforeDelay: number;
    };
    password: {
        /**
         * Password verifier Service name
         */
        verifier?: string;
        /**
         * Regexp that password must check
         * @default "{8,}"
         */
        regexp?: string;
    };
    /**
     * Number of salt iteration for bcrypt.hashSync
     */
    salt: string;
    /**
     * Redirect to this page when email validation failed
     */
    failureRedirect: string;
    /**
     * Redirect to this page when email validation succeed
     */
    successRedirect: string;
    /**
     * Redirect to this page once email is validate to finish the registration process
     */
    registerRedirect: string;
    constructor(params: any);
}
export type AuthenticationEvents = {
    "Authentication.GetMe": EventAuthenticationGetMe;
    "Authentication.Register": EventAuthenticationRegister;
    "Authentication.PasswordUpdate": EventAuthenticationPasswordUpdate;
    "Authentication.Logout": EventAuthenticationLogout;
    "Authentication.Login": EventAuthenticationLogin;
    "Authentication.LoginFailed": EventAuthenticationLoginFailed;
    "Authentication.PasswordCreate": EventAuthenticationPasswordUpdate;
};
/**
 * This class is known as the Authentication module
 * It handles OAuth for several providers for now (Facebook, Google, Amazon, GitHub and Twitter)
 * It also handles email authentication with prevalidation or postvalidation of the email
 *
 * It requires two Store to work one `idents` and one `users`
 *
 * The parameters are
 * ```
 *   providerName: {
 *     clientID: '...',
 *     clientSecret: '...',
 *     scope: ''
 *   },
 *   email: {
 *	    postValidation: true|false   // If postValidation=true, account created without email verification
 *   }
 *   url: 'url' // By default /auth
 * ```
 *
 * @category CoreServices
 * @WebdaModda
 */
declare class Authentication<T extends AuthenticationParameters = AuthenticationParameters, E extends AuthenticationEvents = AuthenticationEvents> extends Service<T, E> {
    _identModel: CoreModelDefinition<Ident>;
    _userModel: CoreModelDefinition<User>;
    /**
     * Used for hmac
     */
    cryptoService: CryptoService;
    _passwordVerifier: PasswordVerifier;
    providers: Set<string>;
    metrics: {
        login: Counter;
        logout: Counter;
        loginFailed?: Counter;
        recovery?: Counter;
        recovered?: Counter;
        registration?: Counter;
    };
    /**
     * Load the parameters for a service
     */
    loadParameters(params: any): AuthenticationParameters;
    /**
     * Get the user store
     * @returns
     */
    getUserStore<K extends User = User>(): Store<K>;
    /**
     * Get the user store
     * @returns
     */
    getIdentStore<K extends Ident = Ident>(): Store<K>;
    /**
     * @ignore
     * Setup the default routes
     */
    computeParameters(): void;
    /**
     * @override
     */
    initMetrics(): void;
    /**
     * Add a provider to the oauth scheme
     * @param name
     */
    addProvider(name: string): void;
    /**
     * Ensure email is enabled for all emails routes
     * @override
     */
    getUrl(url: string, methods: HttpMethodType[]): string;
    /**
     * Send or resend an email to validate the email address
     *
     * @param ctx
     * @throws 409 if ident is linked to someone else
     * @throws 412 if the email is already validated
     * @throws 429 if a validation email has been sent recently
     */
    _sendEmailValidation(ctx: any): Promise<void>;
    /**
     * Return current user
     * @param ctx
     */
    _getMe(ctx: OperationContext): Promise<void>;
    /**
     * Handle both list of available authentication
     * and logout with method 'DELETE'
     *
     * @param ctx
     * @returns
     */
    _listAuthentications(ctx: WebContext): Promise<void>;
    onIdentLogin(ctx: WebContext, provider: string, identId: string, profile: any, tokens?: any): Promise<void>;
    /**
     * Create a new User with the link ident
     * @param ident
     */
    createUserWithIdent(provider: string, identId: string, profile?: any): Promise<void>;
    registerUser(ctx: WebContext, data: any, identId: string, user?: User): Promise<User>;
    getPasswordRecoveryInfos(uuid: string | User, interval?: number): Promise<PasswordRecoveryInfos>;
    /**
     * Manage password recovery
     * @param ctx
     */
    _passwordRecoveryEmail(ctx: WebContext): Promise<void>;
    _verifyPassword(password: string, user?: User): Promise<void>;
    _passwordRecovery(ctx: WebContext<PasswordRecoveryBody>): Promise<void>;
    /**
     * Callback to validate an email address
     * @param ctx
     * @returns
     */
    _handleEmailCallback(ctx: WebContext): Promise<void>;
    /**
     * Send an email to recover the user password
     *
     * @param ctx
     * @param user
     * @param email
     * @returns
     */
    sendRecoveryEmail(ctx: WebContext, user: any, email: string): Promise<any>;
    /**
     * Send an email to validate the user email by sending a unique link to
     * his email
     *
     * @param ctx
     * @param email
     * @returns
     */
    sendValidationEmail(ctx: WebContext, email: string): Promise<any>;
    /**
     * Check the password match the stored hash
     * @param hash generate prior by hashPassword
     * @param password as entered by the user
     */
    checkPassword(hash: string, pass: string): boolean;
    /**
     * Hash the password according to good practices
     *
     * @param pass to hash
     */
    hashPassword(pass: string): string;
    /**
     * Logout user
     */
    logout(ctx: WebContext): Promise<void>;
    /**
     * Login a user
     *
     * @param ctx
     * @param user
     * @param ident
     * @returns
     */
    login(ctx: WebContext, user: User | string, ident: Ident, provider: string): Promise<any[]>;
    getMailMan(): Mailer;
    /**
     * Handle a user login request
     *
     * @param ctx
     * @param ident
     */
    protected handleLogin(ctx: WebContext<LoginBody>, ident: Ident): Promise<void>;
    /**
     * Handle the POST /auth/email
     *
     * @param ctx
     * @returns
     */
    _handleEmail(ctx: WebContext<LoginBody>): Promise<any>;
    generateEmailValidationToken(user: string, email: string): Promise<string>;
}
export { Authentication };
