"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const chai_1 = require("chai");
const chai = require("chai");
chai.use(require('chai-as-promised'));
const faker = require("faker");
const sinon = require("sinon");
const moment = require("moment");
const PasswordAuthProvider_1 = require("./PasswordAuthProvider");
const __1 = require("..");
const errors = require("../../errors");
const TestServer_1 = require("../../TestServer");
describe("PasswordAuthProvider", () => {
    let provider;
    let server;
    let authService;
    function createServer(params = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            server = new TestServer_1.TestServer();
            provider = new PasswordAuthProvider_1.PasswordAuthProvider(Object.assign(params, { iterations: 1 }));
            yield server.start({
                authProviders: [provider],
            });
            authService = server.getService('auth');
        });
    }
    afterEach(() => __awaiter(this, void 0, void 0, function* () {
        if (server) {
            yield server.shutdown();
        }
    }));
    describe("password functions", () => {
        beforeEach(() => __awaiter(this, void 0, void 0, function* () { return createServer(); }));
        it('should be able to create a salt with the configured provider.iterations', function () {
            return __awaiter(this, void 0, void 0, function* () {
                const buffer = yield provider['createSalt'](provider['iterations']);
                chai_1.expect(buffer).to.not.be.empty;
            });
        });
        it('should be able to compare a password ', function () {
            return __awaiter(this, void 0, void 0, function* () {
                const salt = yield provider['createSalt'](provider['saltLength']);
                const hash = yield provider['hashPassword']('iloverealm', salt, provider['iterations'], provider['keyLength'], provider['digest']);
                const isMatch = yield provider['comparePassword']('iloverealm', salt, provider['iterations'], provider['keyLength'], provider['digest'], hash);
                chai_1.expect(isMatch).to.be.true;
            });
        });
        it('should be false when comparing a bad password', function () {
            return __awaiter(this, void 0, void 0, function* () {
                const salt = yield provider['createSalt'](provider['saltLength']);
                const hash = yield provider['hashPassword']('iloverealm', salt, provider['iterations'], provider['keyLength'], provider['digest']);
                const isMatch = yield provider['comparePassword']('bad password', salt, provider['iterations'], provider['keyLength'], provider['digest'], hash);
                chai_1.expect(isMatch).to.be.false;
            });
        });
        it('should be false when changing the digest method', function () {
            return __awaiter(this, void 0, void 0, function* () {
                const salt = yield provider['createSalt'](provider['saltLength']);
                const hash = yield provider['hashPassword']('iloverealm', salt, provider['iterations'], provider['keyLength'], 'sha512');
                const isMatch = yield provider['comparePassword']('iloverealm', salt, provider['iterations'], provider['keyLength'], 'sha256', hash);
                chai_1.expect(isMatch).to.be.false;
            });
        });
        it('should be false when changing the iterations', function () {
            return __awaiter(this, void 0, void 0, function* () {
                const salt = yield provider['createSalt'](provider['saltLength']);
                const hash = yield provider['hashPassword']('iloverealm', salt, provider['iterations'], provider['keyLength'], provider['digest']);
                const isMatch = yield provider['comparePassword']('iloverealm', salt, provider['iterations'] + 5, provider['keyLength'], provider['digest'], hash);
                chai_1.expect(isMatch).to.be.false;
            });
        });
        it('should be false when changing the keyLength', function () {
            return __awaiter(this, void 0, void 0, function* () {
                const salt = yield provider['createSalt'](provider['saltLength']);
                const hash = yield provider['hashPassword']('iloverealm', salt, provider['iterations'], provider['keyLength'], provider['digest']);
                const isMatch = yield provider['comparePassword']('iloverealm', salt, provider['iterations'], provider['keyLength'] + 123, provider['digest'], hash);
                chai_1.expect(isMatch).to.be.false;
            });
        });
    });
    describe("authenticateOrCreateUser", () => {
        beforeEach(() => __awaiter(this, void 0, void 0, function* () { return createServer(); }));
        it("should throw an error when a username is not passed", () => __awaiter(this, void 0, void 0, function* () {
            yield chai_1.assert.isRejected(provider.authenticateOrCreateUser({}), errors.realm.MissingParameters);
        }));
        it("should throw an error when a password is not passed", () => __awaiter(this, void 0, void 0, function* () {
            yield chai_1.assert.isRejected(provider.authenticateOrCreateUser({
                username: 'user1',
            }), errors.realm.MissingParameters);
        }));
        it("should throw an error when register is false", () => __awaiter(this, void 0, void 0, function* () {
            yield chai_1.assert.isRejected(provider.authenticateOrCreateUser({
                username: 'user1',
                password: "mypassword",
                register: false
            }), errors.realm.InvalidCredentials);
        }));
        it("should fulfill when register is true", () => __awaiter(this, void 0, void 0, function* () {
            yield chai_1.assert.isFulfilled(provider.authenticateOrCreateUser({
                username: 'user1',
                password: "mypassword",
                register: true,
            }));
        }));
    });
    describe("update", () => {
        beforeEach(() => __awaiter(this, void 0, void 0, function* () { return createServer(); }));
        let username;
        let user;
        beforeEach(() => __awaiter(this, void 0, void 0, function* () {
            username = faker.internet.userName();
            user = yield authService.createOrUpdateUser(username, "password", false);
        }));
        it("should raise an error when new_password is not passed", () => __awaiter(this, void 0, void 0, function* () {
            yield chai_1.assert.isRejected(provider.update(user, {
                currentPassword: "oldPassword"
            }), errors.realm.MissingParameters);
        }));
        it("should change the user's password", () => __awaiter(this, void 0, void 0, function* () {
            yield chai_1.assert.isFulfilled(provider.update(user, {
                new_password: "Rod.Smith"
            }));
            yield chai_1.assert.isFulfilled(provider['attemptToLogin'](username, 'Rod.Smith'));
        }));
    });
    describe("autoCreateAdminUser", () => {
        beforeEach(() => __awaiter(this, void 0, void 0, function* () { return createServer({ autoCreateAdminUser: true }); }));
        it('should create realm-admin upon autokeygen', function () {
            return __awaiter(this, void 0, void 0, function* () {
                const realmAdminUser = authService.getUserByProviderId("password", "realm-admin");
                chai_1.assert.isDefined(realmAdminUser);
                chai_1.assert.isTrue(realmAdminUser.isAdmin);
                chai_1.assert.equal(realmAdminUser.accounts[0].provider, 'password');
                chai_1.assert.equal(realmAdminUser.accounts[0].providerId, 'realm-admin');
                const loggedInUser = yield provider["attemptToLogin"]('realm-admin', '');
                chai_1.assert.isDefined(loggedInUser);
                chai_1.assert.equal(loggedInUser.userId, realmAdminUser.userId);
                chai_1.assert.equal(loggedInUser.accounts[0].provider, 'password');
                chai_1.assert.equal(loggedInUser.accounts[0].providerId, 'realm-admin');
                chai_1.assert.isTrue(loggedInUser.isAdmin);
            });
        });
    });
    describe("createUserChangePasswordHashParametersLoginUser", () => {
        beforeEach(() => __awaiter(this, void 0, void 0, function* () { return yield createServer(); }));
        it('should login after changing password hash parameters', function () {
            return __awaiter(this, void 0, void 0, function* () {
                const user_1 = yield provider.authenticateOrCreateUser({
                    username: 'some name',
                    password: "mypassword",
                    register: true,
                });
                chai_1.assert.equal(user_1.accounts.length, 1);
                chai_1.assert.equal(user_1.accounts[0].provider, "password");
                chai_1.assert.equal(user_1.accounts[0].providerId, "some name");
                provider['iterations'] = 1000000;
                provider['keyLength'] = 123;
                provider['digest'] = 'sha256';
                const user_2 = yield provider.authenticateOrCreateUser({
                    username: 'some name',
                    password: "mypassword",
                    register: false,
                });
                chai_1.assert.equal(user_1.userId, user_2.userId);
            });
        });
    });
    describe("deleteUser", () => {
        beforeEach(() => __awaiter(this, void 0, void 0, function* () { return createServer(); }));
        it('Password Realm should be empty after creating a user and deleting it', () => __awaiter(this, void 0, void 0, function* () {
            const user = yield provider.authenticateOrCreateUser({
                username: 'some name',
                password: "mypassword",
                register: true,
            });
            const realm = provider['passwordRealm'];
            const foundPasswordBefore = realm.objectForPrimaryKey('PasswordSaltHash', user.userId);
            chai_1.assert.exists(foundPasswordBefore);
            const userDeleted = yield provider.deleteUser(user.userId);
            chai_1.assert.isTrue(userDeleted);
            const userDeletedAgain = yield provider.deleteUser(user.userId);
            chai_1.assert.isFalse(userDeletedAgain);
            const foundPasswordAfter = realm.objectForPrimaryKey('PasswordSaltHash', user.userId);
            chai_1.assert.notExists(foundPasswordAfter);
        }));
    });
    describe("createUserChangePasswordHashParametersLoginUser", () => {
        beforeEach(() => __awaiter(this, void 0, void 0, function* () { return createServer(); }));
        it('should fail when the user attempts to login after the password is deleted from the password Realm', () => __awaiter(this, void 0, void 0, function* () {
            const user = yield provider.authenticateOrCreateUser({
                username: 'some name',
                password: "mypassword",
                register: true,
            });
            chai_1.assert.equal(user.accounts.length, 1);
            chai_1.assert.equal(user.accounts[0].provider, "password");
            chai_1.assert.equal(user.accounts[0].providerId, "some name");
            const userDeleted = yield provider.deleteUser(user.userId);
            chai_1.assert.isTrue(userDeleted);
            yield chai_1.assert.isRejected(provider.authenticateOrCreateUser({
                username: 'some name',
                password: "mypassword",
                register: false,
            }));
        }));
    });
    describe('updateProviderAccount', () => {
        describe('when configured', () => {
            const userEmail = 'user1@gmail.com';
            let user;
            let emailHandler;
            let resetPasswordStub;
            let confirmEmailStub;
            beforeEach(() => __awaiter(this, void 0, void 0, function* () {
                emailHandler = {
                    resetPassword: (email, token, userAgent, remoteIp) => __awaiter(this, void 0, void 0, function* () { }),
                    confirmEmail: (email, token) => __awaiter(this, void 0, void 0, function* () { }),
                };
                resetPasswordStub = sinon.stub(emailHandler, 'resetPassword').callsFake(() => __awaiter(this, void 0, void 0, function* () { }));
                confirmEmailStub = sinon.stub(emailHandler, 'confirmEmail').callsFake(() => __awaiter(this, void 0, void 0, function* () { }));
                yield createServer({
                    emailHandler
                });
                user = yield provider.authenticateOrCreateUser({
                    username: userEmail,
                    password: 'mypassword',
                    register: true,
                });
            }));
            describe('when action is reset_password', () => {
                it('invokes the email handler', () => __awaiter(this, void 0, void 0, function* () {
                    const userAgent = {
                        os: 'Windows',
                        browser: 'Chrome'
                    };
                    const ip = '127.0.0.1';
                    yield chai_1.assert.isFulfilled(provider.updateProviderAccount(userEmail, user, {
                        action: 'reset_password'
                    }, false, userAgent, ip));
                    sinon.assert.calledOnce(resetPasswordStub);
                    const callArgs = resetPasswordStub.getCall(0).args;
                    chai_1.assert.strictEqual(callArgs[0], userEmail);
                    chai_1.assert.isDefined(callArgs[1]);
                    chai_1.assert.deepEqual(callArgs[2], userAgent);
                    chai_1.assert.strictEqual(callArgs[3], ip);
                }));
                describe('when email handler throws', () => {
                    it('should log error', () => __awaiter(this, void 0, void 0, function* () {
                        const error = {
                            title: 'Email sending failed',
                            reason: 'Invalid email address'
                        };
                        resetPasswordStub.callsFake(() => __awaiter(this, void 0, void 0, function* () {
                            throw error;
                        }));
                        const authService = server.getService('auth');
                        let logStub;
                        const logPromise = new Promise((resolve) => {
                            logStub = sinon.stub(authService.logger, 'error').callsFake(() => {
                                resolve();
                            });
                        });
                        yield chai_1.assert.isFulfilled(provider.updateProviderAccount(userEmail, user, {
                            action: 'reset_password'
                        }, false, {}, ''));
                        sinon.assert.calledOnce(resetPasswordStub);
                        yield logPromise;
                        sinon.assert.calledOnce(logStub);
                        const logArgs = logStub.getCall(0).args;
                        chai_1.assert.equal(logArgs[0], 'Could not send reset email:');
                        chai_1.assert.deepEqual(logArgs[1], error);
                    }));
                });
            });
            describe('when action is complete_reset', () => {
                it('fails when new_password is not provided', () => __awaiter(this, void 0, void 0, function* () {
                    const err = yield chai_1.assert.isRejected(provider.updateProviderAccount(undefined, undefined, {
                        action: 'complete_reset',
                        token: '123'
                    }, false, {}, ''), errors.realm.MissingParameters);
                    chai_1.assert.equal(err.invalidParams.length, 1);
                    chai_1.assert.equal(err.invalidParams[0].name, 'new_password');
                }));
                it('fails when token is not provided', () => __awaiter(this, void 0, void 0, function* () {
                    const err = yield chai_1.assert.isRejected(provider.updateProviderAccount(undefined, undefined, {
                        action: 'complete_reset',
                        new_password: ''
                    }, false, {}, ''), errors.realm.MissingParameters);
                    chai_1.assert.equal(err.invalidParams.length, 1);
                    chai_1.assert.equal(err.invalidParams[0].name, 'token');
                }));
                it('fails when token is invalid', () => __awaiter(this, void 0, void 0, function* () {
                    yield chai_1.assert.isRejected(provider.updateProviderAccount(undefined, undefined, {
                        action: 'complete_reset',
                        new_password: '',
                        token: '123'
                    }, false, {}, ''), errors.realm.AccessDenied);
                }));
                it('fails when token is expired', () => __awaiter(this, void 0, void 0, function* () {
                    yield chai_1.assert.isFulfilled(provider.updateProviderAccount(userEmail, user, {
                        action: 'reset_password'
                    }, false, {}, ''));
                    const token = resetPasswordStub.getCall(0).args[1];
                    const passwordRealm = provider['passwordRealm'];
                    const existing = passwordRealm.objectForPrimaryKey('PasswordResetRequest', token);
                    chai_1.assert.isDefined(existing);
                    passwordRealm.write(() => {
                        existing.expires = moment().subtract(1, 'hour').toDate();
                    });
                    yield chai_1.assert.isRejected(provider.updateProviderAccount(undefined, undefined, {
                        action: 'complete_reset',
                        new_password: '',
                        token
                    }, false, {}, ''), errors.realm.AccessDenied);
                }));
                it('fails when token was consumed', () => __awaiter(this, void 0, void 0, function* () {
                    yield chai_1.assert.isFulfilled(provider.updateProviderAccount(userEmail, user, {
                        action: 'reset_password'
                    }, false, {}, ''));
                    const token = resetPasswordStub.getCall(0).args[1];
                    yield chai_1.assert.isFulfilled(provider.updateProviderAccount(undefined, undefined, {
                        action: 'complete_reset',
                        new_password: '123',
                        token
                    }, false, {}, ''));
                    yield chai_1.assert.isRejected(provider.updateProviderAccount(undefined, undefined, {
                        action: 'complete_reset',
                        new_password: '123',
                        token
                    }, false, {}, ''), errors.realm.AccessDenied);
                }));
                it('changes the password', () => __awaiter(this, void 0, void 0, function* () {
                    yield chai_1.assert.isFulfilled(provider.updateProviderAccount(userEmail, user, {
                        action: 'reset_password'
                    }, false, {}, ''));
                    const token = resetPasswordStub.getCall(0).args[1];
                    yield chai_1.assert.isFulfilled(provider.updateProviderAccount(undefined, undefined, {
                        action: 'complete_reset',
                        new_password: '123',
                        token
                    }, false, {}, ''));
                    yield chai_1.assert.isRejected(provider.authenticateOrCreateUser({
                        username: userEmail,
                        password: 'mypassword',
                        register: false,
                    }), errors.realm.InvalidCredentials);
                    yield chai_1.assert.isFulfilled(provider.authenticateOrCreateUser({
                        username: userEmail,
                        password: '123',
                        register: false,
                    }));
                }));
            });
            describe('when action is request_email_confirmation', () => {
                it('invokes the email handler', () => __awaiter(this, void 0, void 0, function* () {
                    confirmEmailStub.resetHistory();
                    yield chai_1.assert.isFulfilled(provider.updateProviderAccount(userEmail, user, {
                        action: 'request_email_confirmation'
                    }, false, {}, ''));
                    sinon.assert.calledOnce(confirmEmailStub);
                    const callArgs = confirmEmailStub.getCall(0).args;
                    chai_1.assert.strictEqual(callArgs[0], userEmail);
                    chai_1.assert.isDefined(callArgs[1]);
                }));
            });
            describe('when action is confirm_email', () => {
                const loginViaService = () => {
                    return authService['authenticate']({
                        provider: provider.name,
                        username: userEmail,
                        password: 'mypassword',
                        register: false,
                    });
                };
                it('fails when token is not provided', () => __awaiter(this, void 0, void 0, function* () {
                    const err = yield chai_1.assert.isRejected(provider.updateProviderAccount(undefined, undefined, {
                        action: 'confirm_email'
                    }, false, {}, ''), errors.realm.MissingParameters);
                    chai_1.assert.equal(err.invalidParams.length, 1);
                    chai_1.assert.equal(err.invalidParams[0].name, 'token');
                }));
                it('fails when token is invalid', () => __awaiter(this, void 0, void 0, function* () {
                    yield chai_1.assert.isRejected(provider.updateProviderAccount(undefined, undefined, {
                        action: 'confirm_email',
                        token: '123'
                    }, false, {}, ''), errors.realm.AccessDenied);
                }));
                it('fails when token is expired', () => __awaiter(this, void 0, void 0, function* () {
                    yield chai_1.assert.isFulfilled(provider.updateProviderAccount(userEmail, user, {
                        action: 'request_email_confirmation'
                    }, false, {}, ''));
                    const token = confirmEmailStub.getCall(0).args[1];
                    const passwordRealm = provider['passwordRealm'];
                    const existing = passwordRealm.objectForPrimaryKey('EmailConfirmationRequest', token);
                    chai_1.assert.isDefined(existing);
                    passwordRealm.write(() => {
                        existing.expires = moment().subtract(1, 'hour').toDate();
                    });
                    yield chai_1.assert.isRejected(provider.updateProviderAccount(undefined, undefined, {
                        action: 'confirm_email',
                        token
                    }, false, {}, ''), errors.realm.AccessDenied);
                }));
                it('fails when token was consumed', () => __awaiter(this, void 0, void 0, function* () {
                    yield chai_1.assert.isFulfilled(provider.updateProviderAccount(userEmail, user, {
                        action: 'request_email_confirmation'
                    }, false, {}, ''));
                    const token = confirmEmailStub.getCall(0).args[1];
                    yield chai_1.assert.isFulfilled(provider.updateProviderAccount(userEmail, user, {
                        action: 'confirm_email',
                        token
                    }, false, {}, ''));
                    yield chai_1.assert.isRejected(provider.updateProviderAccount(userEmail, user, {
                        action: 'confirm_email',
                        token
                    }, false, {}, ''), errors.realm.AccessDenied);
                }));
                it('confirms the email', () => __awaiter(this, void 0, void 0, function* () {
                    let isConfirmed = user.metadata.find(m => m.key === 'isEmailConfirmed');
                    chai_1.assert.isTrue(!isConfirmed || isConfirmed.value === 'false');
                    let serviceResponse = yield loginViaService();
                    let serviceIsConfirmed = serviceResponse.refresh_token.token_data.isEmailConfirmed;
                    chai_1.assert.isFalse(serviceIsConfirmed);
                    yield chai_1.assert.isFulfilled(provider.updateProviderAccount(userEmail, user, {
                        action: 'request_email_confirmation'
                    }, false, {}, ''));
                    const token = confirmEmailStub.getCall(0).args[1];
                    yield chai_1.assert.isFulfilled(provider.updateProviderAccount(userEmail, user, {
                        action: 'confirm_email',
                        token
                    }, false, {}, ''));
                    const userResponse = yield chai_1.assert.isFulfilled(provider.authenticateOrCreateUser({
                        username: userEmail,
                        password: 'mypassword',
                        register: false,
                    }));
                    isConfirmed = userResponse.metadata.find(m => m.key === 'isEmailConfirmed');
                    chai_1.assert.equal(isConfirmed.value, 'true');
                    serviceResponse = yield loginViaService();
                    serviceIsConfirmed = serviceResponse.refresh_token.token_data.isEmailConfirmed;
                    chai_1.assert.isTrue(serviceIsConfirmed);
                }));
            });
            describe('when action is invalid', () => {
                it('throws an error', () => __awaiter(this, void 0, void 0, function* () {
                    yield chai_1.assert.isRejected(provider.updateProviderAccount(userEmail, user, {
                        action: 'some_action'
                    }, false, {}, ''), errors.realm.InvalidParameters);
                }));
            });
        });
        describe('when not configured', () => {
            beforeEach(() => __awaiter(this, void 0, void 0, function* () { return yield createServer(); }));
            it('throws an error', () => __awaiter(this, void 0, void 0, function* () {
                yield chai_1.assert.isRejected(provider.updateProviderAccount('foo@bar.com', undefined, {
                    action: 'reset_password'
                }, false, {}, ''), errors.realm.NotSupported);
            }));
        });
    });
    describe.skip('performance tests', function () {
        this.timeout(1200000);
        beforeEach(() => createServer());
        const measureTime = (toMeasure) => __awaiter(this, void 0, void 0, function* () {
            const start = process.hrtime();
            yield toMeasure();
            const end = process.hrtime(start);
            return Math.round((end[0] * 1000) + (end[1] / 1000000));
        });
        describe('createSalt', () => {
            it('sequential', () => __awaiter(this, void 0, void 0, function* () {
                const testSalt = (length) => __awaiter(this, void 0, void 0, function* () {
                    const result = yield measureTime(() => __awaiter(this, void 0, void 0, function* () {
                        for (let i = 0; i < 500; i++) {
                            const salt = yield provider['createSalt'](length);
                        }
                    }));
                    console.log(`createSalt(length: ${length}) Time: ${result / 500} ms`);
                });
                yield testSalt(8);
                yield testSalt(16);
                yield testSalt(32);
                yield testSalt(64);
                yield testSalt(128);
            }));
            it('parallel', () => __awaiter(this, void 0, void 0, function* () {
                const testSalt = (length) => __awaiter(this, void 0, void 0, function* () {
                    const result = yield measureTime(() => __awaiter(this, void 0, void 0, function* () {
                        const promises = new Array();
                        for (let i = 0; i < 500; i++) {
                            promises.push(provider['createSalt'](length));
                        }
                        yield Promise.all(promises);
                    }));
                    console.log(`createSalt(length: ${length}) Time: ${result / 500} ms`);
                });
                yield testSalt(8);
                yield testSalt(16);
                yield testSalt(32);
                yield testSalt(64);
                yield testSalt(128);
            }));
        });
        describe('password hashing', () => {
            it('sequential', () => __awaiter(this, void 0, void 0, function* () {
                const testHashing = (iterations, saltLength = 32) => __awaiter(this, void 0, void 0, function* () {
                    const result = yield measureTime(() => __awaiter(this, void 0, void 0, function* () {
                        for (let i = 0; i < 100; i++) {
                            const salt = yield provider['createSalt'](saltLength);
                            const hash = yield provider['hashPassword'](faker.random.uuid(), salt, iterations, 512, 'sha512');
                        }
                    }));
                    console.log(`iterations: ${iterations}, salt: ${saltLength}; Time: ${result / 100} ms`);
                });
                yield testHashing(500);
                yield testHashing(1000);
                yield testHashing(2000);
                yield testHashing(5000);
                yield testHashing(7500);
                yield testHashing(10000);
                yield testHashing(20000);
            }));
            it('parallel', () => __awaiter(this, void 0, void 0, function* () {
                const testHashing = (iterations, saltLength = 32) => __awaiter(this, void 0, void 0, function* () {
                    const result = yield measureTime(() => __awaiter(this, void 0, void 0, function* () {
                        const hashPassword = () => __awaiter(this, void 0, void 0, function* () {
                            const salt = yield provider['createSalt'](saltLength);
                            const hash = yield provider['hashPassword'](faker.random.uuid(), salt, iterations, 512, 'sha512');
                        });
                        const promises = new Array();
                        for (let i = 0; i < 100; i++) {
                            promises.push(hashPassword());
                        }
                        yield Promise.all(promises);
                    }));
                    console.log(`iterations: ${iterations}, salt: ${saltLength}; Time: ${result / 100} ms`);
                });
                yield testHashing(500);
                yield testHashing(1000);
                yield testHashing(2000);
                yield testHashing(5000);
                yield testHashing(7500);
                yield testHashing(10000);
                yield testHashing(20000);
            }));
        });
    });
});
describe('UserLoginWithWrongProvider', () => {
    it('should fail when a debug user attempts to log in with the password provider', () => __awaiter(this, void 0, void 0, function* () {
        const passwordProvider = new PasswordAuthProvider_1.PasswordAuthProvider({ iterations: 5 });
        const nicknameProvider = new __1.NicknameAuthProvider();
        const server = new TestServer_1.TestServer();
        yield server.start({
            authProviders: [
                passwordProvider,
                nicknameProvider,
            ]
        });
        const authService = server.getService('auth');
        const user = yield nicknameProvider.authenticateOrCreateUser({
            data: 'some name',
        });
        chai_1.assert.equal(user.accounts.length, 1);
        chai_1.assert.equal(user.accounts[0].provider, "nickname");
        chai_1.assert.equal(user.accounts[0].providerId, "some name");
        yield chai_1.assert.isRejected(passwordProvider.authenticateOrCreateUser({
            username: 'some name',
            password: "mypassword",
            register: false,
        }));
        yield server.shutdown();
    }));
});
//# sourceMappingURL=PasswordAuthProvider.spec.js.map