"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const chai_1 = require("chai");
const core_utils_1 = require("../../../shared/core-utils");
const server_commands_1 = require("../../../shared/server-commands");
function loginExternal(options) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const res = yield options.server.plugins.getExternalAuth({
            npmName: options.npmName,
            npmVersion: '0.0.1',
            authName: options.authName,
            query: options.query,
            expectedStatus: options.expectedStatus || 302
        });
        if (res.status !== 302)
            return;
        const location = res.header.location;
        const { externalAuthToken } = (0, server_commands_1.decodeQueryString)(location);
        const resLogin = yield options.server.login.loginUsingExternalToken({
            username: options.username,
            externalAuthToken: externalAuthToken,
            expectedStatus: options.expectedStatusStep2
        });
        return resLogin.body;
    });
}
describe('Test external auth plugins', function () {
    let server;
    let cyanAccessToken;
    let cyanRefreshToken;
    let kefkaAccessToken;
    let kefkaRefreshToken;
    let externalAuthToken;
    before(function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            this.timeout(30000);
            server = yield (0, server_commands_1.createSingleServer)(1, {
                rates_limit: {
                    login: {
                        max: 30
                    }
                }
            });
            yield (0, server_commands_1.setAccessTokensToServers)([server]);
            for (const suffix of ['one', 'two', 'three']) {
                yield server.plugins.install({ path: server_commands_1.PluginsCommand.getPluginTestPath('-external-auth-' + suffix) });
            }
        });
    });
    it('Should display the correct configuration', function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const config = yield server.config.getConfig();
            const auths = config.plugin.registeredExternalAuths;
            (0, chai_1.expect)(auths).to.have.lengthOf(9);
            const auth2 = auths.find((a) => a.authName === 'external-auth-2');
            (0, chai_1.expect)(auth2).to.exist;
            (0, chai_1.expect)(auth2.authDisplayName).to.equal('External Auth 2');
            (0, chai_1.expect)(auth2.npmName).to.equal('peertube-plugin-test-external-auth-one');
        });
    });
    it('Should redirect for a Cyan login', function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const res = yield server.plugins.getExternalAuth({
                npmName: 'test-external-auth-one',
                npmVersion: '0.0.1',
                authName: 'external-auth-1',
                query: {
                    username: 'cyan'
                },
                expectedStatus: 302
            });
            const location = res.header.location;
            (0, chai_1.expect)(location.startsWith('/login?')).to.be.true;
            const searchParams = (0, server_commands_1.decodeQueryString)(location);
            (0, chai_1.expect)(searchParams.externalAuthToken).to.exist;
            (0, chai_1.expect)(searchParams.username).to.equal('cyan');
            externalAuthToken = searchParams.externalAuthToken;
        });
    });
    it('Should reject auto external login with a missing or invalid token', function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const command = server.login;
            yield command.loginUsingExternalToken({ username: 'cyan', externalAuthToken: '', expectedStatus: 400 });
            yield command.loginUsingExternalToken({ username: 'cyan', externalAuthToken: 'blabla', expectedStatus: 400 });
        });
    });
    it('Should reject auto external login with a missing or invalid username', function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const command = server.login;
            yield command.loginUsingExternalToken({ username: '', externalAuthToken, expectedStatus: 400 });
            yield command.loginUsingExternalToken({ username: '', externalAuthToken, expectedStatus: 400 });
        });
    });
    it('Should reject auto external login with an expired token', function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            this.timeout(15000);
            yield (0, core_utils_1.wait)(5000);
            yield server.login.loginUsingExternalToken({
                username: 'cyan',
                externalAuthToken,
                expectedStatus: 400
            });
            yield server.servers.waitUntilLog('expired external auth token', 4);
        });
    });
    it('Should auto login Cyan, create the user and use the token', function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            {
                const res = yield loginExternal({
                    server,
                    npmName: 'test-external-auth-one',
                    authName: 'external-auth-1',
                    query: {
                        username: 'cyan'
                    },
                    username: 'cyan'
                });
                cyanAccessToken = res.access_token;
                cyanRefreshToken = res.refresh_token;
            }
            {
                const body = yield server.users.getMyInfo({ token: cyanAccessToken });
                (0, chai_1.expect)(body.username).to.equal('cyan');
                (0, chai_1.expect)(body.account.displayName).to.equal('cyan');
                (0, chai_1.expect)(body.email).to.equal('cyan@example.com');
                (0, chai_1.expect)(body.role.id).to.equal(2);
            }
        });
    });
    it('Should auto login Kefka, create the user and use the token', function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            {
                const res = yield loginExternal({
                    server,
                    npmName: 'test-external-auth-one',
                    authName: 'external-auth-2',
                    username: 'kefka'
                });
                kefkaAccessToken = res.access_token;
                kefkaRefreshToken = res.refresh_token;
            }
            {
                const body = yield server.users.getMyInfo({ token: kefkaAccessToken });
                (0, chai_1.expect)(body.username).to.equal('kefka');
                (0, chai_1.expect)(body.account.displayName).to.equal('Kefka Palazzo');
                (0, chai_1.expect)(body.email).to.equal('kefka@example.com');
                (0, chai_1.expect)(body.role.id).to.equal(0);
            }
        });
    });
    it('Should refresh Cyan token, but not Kefka token', function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            {
                const resRefresh = yield server.login.refreshToken({ refreshToken: cyanRefreshToken });
                cyanAccessToken = resRefresh.body.access_token;
                cyanRefreshToken = resRefresh.body.refresh_token;
                const body = yield server.users.getMyInfo({ token: cyanAccessToken });
                (0, chai_1.expect)(body.username).to.equal('cyan');
            }
            {
                yield server.login.refreshToken({ refreshToken: kefkaRefreshToken, expectedStatus: 400 });
            }
        });
    });
    it('Should update Cyan profile', function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            yield server.users.updateMe({
                token: cyanAccessToken,
                displayName: 'Cyan Garamonde',
                description: 'Retainer to the king of Doma'
            });
            const body = yield server.users.getMyInfo({ token: cyanAccessToken });
            (0, chai_1.expect)(body.account.displayName).to.equal('Cyan Garamonde');
            (0, chai_1.expect)(body.account.description).to.equal('Retainer to the king of Doma');
        });
    });
    it('Should logout Cyan', function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            yield server.login.logout({ token: cyanAccessToken });
        });
    });
    it('Should have logged out Cyan', function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            yield server.servers.waitUntilLog('On logout cyan');
            yield server.users.getMyInfo({ token: cyanAccessToken, expectedStatus: 401 });
        });
    });
    it('Should login Cyan and keep the old existing profile', function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            {
                const res = yield loginExternal({
                    server,
                    npmName: 'test-external-auth-one',
                    authName: 'external-auth-1',
                    query: {
                        username: 'cyan'
                    },
                    username: 'cyan'
                });
                cyanAccessToken = res.access_token;
            }
            const body = yield server.users.getMyInfo({ token: cyanAccessToken });
            (0, chai_1.expect)(body.username).to.equal('cyan');
            (0, chai_1.expect)(body.account.displayName).to.equal('Cyan Garamonde');
            (0, chai_1.expect)(body.account.description).to.equal('Retainer to the king of Doma');
            (0, chai_1.expect)(body.role.id).to.equal(2);
        });
    });
    it('Should not update an external auth email', function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            yield server.users.updateMe({
                token: cyanAccessToken,
                email: 'toto@example.com',
                currentPassword: 'toto',
                expectedStatus: 400
            });
        });
    });
    it('Should reject token of Kefka by the plugin hook', function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            this.timeout(10000);
            yield (0, core_utils_1.wait)(5000);
            yield server.users.getMyInfo({ token: kefkaAccessToken, expectedStatus: 401 });
        });
    });
    it('Should unregister external-auth-2 and do not login existing Kefka', function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            yield server.plugins.updateSettings({
                npmName: 'peertube-plugin-test-external-auth-one',
                settings: { disableKefka: true }
            });
            yield server.login.login({ user: { username: 'kefka', password: 'fake' }, expectedStatus: 400 });
            yield loginExternal({
                server,
                npmName: 'test-external-auth-one',
                authName: 'external-auth-2',
                query: {
                    username: 'kefka'
                },
                username: 'kefka',
                expectedStatus: 404
            });
        });
    });
    it('Should have disabled this auth', function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const config = yield server.config.getConfig();
            const auths = config.plugin.registeredExternalAuths;
            (0, chai_1.expect)(auths).to.have.lengthOf(8);
            const auth1 = auths.find(a => a.authName === 'external-auth-2');
            (0, chai_1.expect)(auth1).to.not.exist;
        });
    });
    it('Should uninstall the plugin one and do not login Cyan', function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            yield server.plugins.uninstall({ npmName: 'peertube-plugin-test-external-auth-one' });
            yield loginExternal({
                server,
                npmName: 'test-external-auth-one',
                authName: 'external-auth-1',
                query: {
                    username: 'cyan'
                },
                username: 'cyan',
                expectedStatus: 404
            });
            yield server.login.login({ user: { username: 'cyan', password: null }, expectedStatus: 400 });
            yield server.login.login({ user: { username: 'cyan', password: '' }, expectedStatus: 400 });
            yield server.login.login({ user: { username: 'cyan', password: 'fake' }, expectedStatus: 400 });
        });
    });
    it('Should not login kefka with another plugin', function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            yield loginExternal({
                server,
                npmName: 'test-external-auth-two',
                authName: 'external-auth-4',
                username: 'kefka2',
                expectedStatusStep2: 400
            });
            yield loginExternal({
                server,
                npmName: 'test-external-auth-two',
                authName: 'external-auth-4',
                username: 'kefka',
                expectedStatusStep2: 400
            });
        });
    });
    it('Should not login an existing user email', function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            yield server.users.create({ username: 'existing_user', password: 'super_password' });
            yield loginExternal({
                server,
                npmName: 'test-external-auth-two',
                authName: 'external-auth-6',
                username: 'existing_user',
                expectedStatusStep2: 400
            });
        });
    });
    it('Should be able to login an existing user username and channel', function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            yield server.users.create({ username: 'existing_user2' });
            yield server.users.create({ username: 'existing_user2-1_channel' });
            for (let i = 0; i < 2; i++) {
                const res = yield loginExternal({
                    server,
                    npmName: 'test-external-auth-two',
                    authName: 'external-auth-7',
                    username: 'existing_user2'
                });
                const token = res.access_token;
                const myInfo = yield server.users.getMyInfo({ token });
                (0, chai_1.expect)(myInfo.username).to.equal('existing_user2-1');
                (0, chai_1.expect)(myInfo.videoChannels[0].name).to.equal('existing_user2-1_channel-1');
            }
        });
    });
    it('Should display the correct configuration', function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const config = yield server.config.getConfig();
            const auths = config.plugin.registeredExternalAuths;
            (0, chai_1.expect)(auths).to.have.lengthOf(7);
            const auth2 = auths.find((a) => a.authName === 'external-auth-2');
            (0, chai_1.expect)(auth2).to.not.exist;
        });
    });
    after(function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            yield (0, server_commands_1.cleanupTests)([server]);
        });
    });
    it('Should forward the redirectUrl if the plugin returns one', function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const resLogin = yield loginExternal({
                server,
                npmName: 'test-external-auth-three',
                authName: 'external-auth-7',
                username: 'cid'
            });
            const { redirectUrl } = yield server.login.logout({ token: resLogin.access_token });
            (0, chai_1.expect)(redirectUrl).to.equal('https://example.com/redirectUrl');
        });
    });
    it('Should call the plugin\'s onLogout method with the request', function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const resLogin = yield loginExternal({
                server,
                npmName: 'test-external-auth-three',
                authName: 'external-auth-8',
                username: 'cid'
            });
            const { redirectUrl } = yield server.login.logout({ token: resLogin.access_token });
            (0, chai_1.expect)(redirectUrl).to.equal('https://example.com/redirectUrl?access_token=' + resLogin.access_token);
        });
    });
});
//# sourceMappingURL=external-auth.js.map