/// <reference types="node" />
import { Sofa } from '@sl-nx/sofa-model';
import { EventEmitter } from 'events';
import { Request } from 'express';
import { DocumentScope, ServerScope } from 'nano';
import { Mailer } from './mailer';
import { Config } from './types/config';
import { ConsentRequest, CouchDbAuthDoc, CreateSessionOpts, HashResult, LocalHashObj, RegistrationForm, SlAction, SlLoginSession, SlRefreshSession, SlRequest, SlUserDoc } from './types/typings';
export declare enum ValidErr {
    'exists' = "already in use",
    'emailInvalid' = "invalid email",
    'userInvalid' = "invalid username"
}
export declare class User {
    protected config: Config;
    userDB: DocumentScope<SlUserDoc>;
    couchAuthDB: DocumentScope<CouchDbAuthDoc>;
    protected mailer: Mailer;
    emitter: EventEmitter;
    protected couchServer: ServerScope;
    private dbAuth;
    private userDbManager;
    private session;
    private onCreateActions;
    private onLinkActions;
    private hasher;
    private passwordConstraints;
    /**
     * Checks that a username is valid and not in use.
     * Resolves with nothing if successful.
     * Resolves with an error object in failed.
     */
    validateUsername: (v: string) => Promise<string | void>;
    /**
     * Checks that an email is valid and not in use.
     * Resolves with nothing if successful.
     * Resolves with an error object in failed.
     */
    validateEmail: (v: string) => Promise<string | void>;
    /** Validates whether the _format_ matches the config */
    private validateConsents;
    /** @internal */
    userModel: Sofa.AsyncOptions;
    private resetPasswordModel;
    private changePasswordModel;
    constructor(config: Config, userDB: DocumentScope<SlUserDoc>, couchAuthDB: DocumentScope<CouchDbAuthDoc>, mailer: Mailer, emitter: EventEmitter, couchServer: ServerScope);
    /**
     * Hashes a password using PBKDF2 and returns an object containing `salt` and
     * `derived_key`.
     */
    hashPassword(pw: string): Promise<HashResult>;
    /**
     * Verifies a password using a hash object. If you have a user doc, pass in
     * `local` as the hash object.
     * @returns resolves with `true` if valid, `false` if not
     */
    verifyPassword(obj: LocalHashObj, pw: string): Promise<boolean>;
    /**
     * Use this to add as many functions as you want to transform the new user
     * document before it is saved. Your function should accept two arguments
     * (userDoc, provider) and return a Promise that resolves to the modified
     * user document.
     * onCreate functions will be chained in the order they were added.
     * @param {Function} fn
     */
    onCreate(fn: SlAction): void;
    /**
     * Does the same thing as onCreate, but is called every time a user links a
     * new provider, or their profile information is refreshed.
     * This allows you to process profile information and, for example, create a
     * master profile.
     * If an object called profile exists inside the user doc it will be passed
     * to the client along with session information at each login.
     */
    onLink(fn: SlAction): void;
    /** Validation function for ensuring that two fields match */
    private matches;
    private processTransformations;
    /**
     * retrieves by email (default) or username or uuid if the config options are
     * set. Rejects if no valid format.
     */
    getUser(login: string, allowUUID?: boolean): Promise<SlUserDoc | null>;
    private handleEmailExists;
    /**
     * Creates a new local user with a username/email and password.
     * @param form requires the following: `username` and/or `email`, `password`,
     * and `confirmPassword`. `name` is optional. Any additional fields must be
     * whitelisted in your config under `userModel` or they will be removed.
     * @param req additional request data passed to the email template
     * @returns `SlUserDoc` of the created user. Note that the `_rev` won't be
     * correct if `config.security.loginOnRegistration` is `false`: This is done
     * to prevent [time-based attacks](https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html#authentication-responses).
     * Send a response right after this function resolves and subscribe to the
     * `signup` event instead for further processing.
     */
    createUser(form: RegistrationForm, req?: any): Promise<void | SlUserDoc>;
    private prepareNewUser;
    private insertNewUserDocument;
    /**
     * Creates a new user following authentication from an OAuth provider.
     * If the user already exists it will update the profile.
     * @param provider the name of the provider in lowercase, (e.g. 'facebook')
     * @param {any} auth credentials supplied by the provider
     * @param {any} profile the profile supplied by the provider
     */
    createUserSocial(provider: string, auth: any, profile: any): Promise<SlUserDoc>;
    /**
     * like `createUserSocial`, but for an already existing user identified by
     * `login`
     */
    linkUserSocial(login: string, provider: string, auth: any, profile: any): Promise<SlUserDoc>;
    /**
     * Removes the specified provider from the user's account.
     * `local` cannot be removed. If there is only one provider left it will fail.
     * Returns the modified user, if successful.
     * @param login email, username or UUID
     * @param provider the OAuth provider
     */
    unlinkUserSocial(login: string, provider: string): Promise<SlUserDoc>;
    /**
     * Creates a new session for a user
     * @param params: The login options.
     *    - `login`: the email, username or UUID (depending on your config)
     *    - `provider`: 'local' or one of the configured OAuth providers
     *    - `byUUID`: if `true`, interpret `login` always as UUID
     *    - `sessionType`: see `security` -> `sessionConfig` for details
     * @returns the new session
     */
    createSession(params: CreateSessionOpts): Promise<SlLoginSession>;
    /**
     * Extends the life of your current token and returns updated token information.
     * The only field that will change is expires. Expired sessions are removed.
     * todo:
     * - handle error if invalid state occurs that doc is not present.
     */
    refreshSession(sessionId: string): Promise<SlRefreshSession>;
    /**
     * Required form fields: token, password, and confirmPassword
     */
    resetPassword(form: any, req?: Partial<Request>): Promise<SlUserDoc>;
    /**
     * Changes the password of a user, validating the provided data.
     * @param login the `email`, `_id` or `key` of the `sl-user` to updated
     * @param form `newPassword`, `confirmPassword` (same) and `currentPassword`
     * as sent by the user.
     * @param req additional data that will be passed to the template as `req`
     */
    changePasswordSecure(login: string, form: any, req?: any): Promise<void>;
    forgotUsername(email: string, req: Partial<Request>): Promise<void>;
    /**
     * Changes the password of a user. Note that this method does not perform
     * any validations of the supplied password as `changePasswordSecure` does.
     * @param user_uid the UUID of the user (without hypens, `_id` in `sl-users`)
     * @param newPassword the new password for the user
     * @param userDoc the `SlUserDoc` of the user. Will be retrieved by the
     * `user_uid` if not passed.
     * @param req additional data that will be passed to the template as `req`
     */
    changePassword(user_uid: string, newPassword: string, userDoc?: SlUserDoc, req?: any): Promise<void>;
    private sendModifiedPasswordEmail;
    /**
     * sends out a passwort reset email, if the user exists
     * @param email email of the user
     * @param req additional request data, passed to the template as `req`
     */
    forgotPassword(email: string, req: any): Promise<void>;
    private completeForgotPassRequest;
    /**
     * Marks the user's email as verified. `token` comes from the confirmation
     * email. Resolves if the verification is successful or the token was still
     * saved from a previous verification. Rejects if token is invalid.
     * @param token
     */
    verifyEmail(token: string): Promise<void>;
    private markEmailAsVerified;
    private completeEmailChange;
    /**
     * Changes the user's email. If email verification is enabled
     * (`local.sendConfirmEmail`), a confirmation email will be sent out.
     * @param login user's email, username or UUID (depending on your config)
     * @param newEmail the new email
     * @param req additional request data, passed to the template as `req`
     */
    changeEmail(login: string, newEmail: string, req: Partial<SlRequest>): Promise<void>;
    /**
     * Deauthorizes the specified database from the user's account, and optionally destroys it.
     * @param login email, username or UUID of the user (depending on your config)
     * @param dbName full path for a shared db, or base name for a private db
     * @param deletePrivate when true, will destroy a private DB with the `dbName`
     * @param deleteShared when true, will destroy a shared DB with the `dbName.
     *                     Caution: may destroy other users' data!
     */
    removeUserDB(login: string, dbName: string, deletePrivate?: boolean, deleteShared?: boolean): Promise<import("nano").DocumentInsertResponse>;
    /**
     * Logs out all of a user's sessions. One of `login` or `session_id` must be
     * provided.
     * @param login the email, username or UUID of the user
     * @param session_id the id of the session - i.e. `org.couchdb.user:${suffix}`
     * @returns
     */
    logoutAll(login: string, session_id: string): Promise<import("nano").DocumentInsertResponse>;
    /**
     * Logs out the specified session. Note that in case of a server error, it can
     * happen that only the entry in the `_users` DB is removed. This deauthorizes
     * the user, but the records in `sl-users` might not be accurate in that case.
     */
    logoutSession(session_id: string): Promise<{}>;
    /** Logs out all of a user's sessions, except for the one specified. */
    logoutOthers(sessionId: string): Promise<false | import("nano").DocumentInsertResponse>;
    /**
     * Removes a user and terminates all of his sessions
     * @param login the user's uuid or email/key
     * @param destroyDBs use `true` to also remove the personal DBs of the user
     * @param reason additional information to be emmitted by `'user-deleted'`
     */
    removeUser(login: string, destroyDBs?: boolean, reason?: string): Promise<void>;
    /**
     * Confirms the user:password that has been passed as Bearer Token. Returns
     * the passed `key` + the `user_uid`, `expires`, `roles`, `provider` from the
     * the contents of the doc in the `_users`-DB.
     */
    confirmSession(key: string, password: string): Promise<{
        key: string;
        user_uid: string;
        expires: number;
        roles: string[];
        provider: string;
    }>;
    /**
     * Associates a new database with the user's account. Will also authenticate
     * all existing sessions with the new database. If the optional fields are not
     * specified, they will be taken from `userDBs.model.{dbName}` or
     * `userDBs.model._default` in your config.
     * @param login  the `key`, `email` or `_id` (user_uid) of the user
     * @param dbName the name of the database. For a shared db, this is the actual
     * path. For a private db userDBs.privatePrefix will be prepended, and
     * `${user_uid}` appended.
     * @param type 'private' (default) or 'shared'
     * @param designDocs the name of the designDoc (if any) that will be seeded.
     */
    addUserDB(login: string, dbName: string, type?: 'private' | 'shared', designDocs?: any, partitioned?: any): Promise<import("nano").DocumentInsertResponse>;
    /**
     * Adds the private and authorises access to the shared userDBs
     */
    private addUserDBs;
    /**
     * Deauthorizes all expired keys from the authentification-DB (`_users`) and
     * superlogin's db (`sl-users`). Call this regularily!
     */
    removeExpiredKeys(): Promise<string[]>;
    /**
     * @internal
     * returns the latest entries of the current user's consents
     */
    getCurrentConsents(login: string): Promise<Record<string, import("./types/typings").ConsentSlEntry>>;
    /**
     * @internal
     * validates and performs the update to the consents, returning the updated
     * consents if successful
     */
    updateConsents(login: string, consentUpdate: Record<string, ConsentRequest>): Promise<Record<string, import("./types/typings").ConsentSlEntry>>;
}
