"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());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
const iso_libs_1 = require("../libs/iso-libs");
/**
 * token handed over to the user's browser, serves as password to encrypt/decrypt the Medium-access token
 * @type {string}
 */
const IC_WEB_TOKEN = "IC_WEB_TOKEN";
/**
 * unique id of the user, comes from the provider (GitHub, Medium, etc)
 * @type {string}
 */
exports.IC_USER_ID = 'IC_USER_ID';
/**
 * This is an Express middleware that checks whether there is a cookie in the header that contains valid login
 * data
 *
 * @param req
 * @param res
 * @param next
 * @returns if successful, it calls the next middleware, if not, it throws an exception that causes the
 * next error handler to be called
 */
exports.createAuthMiddleware = (clientSecret, onAuthenticated) => (req, res, next) => {
    console.log("createAuthMiddleware", req.universalCookies);
    const webtoken = req.universalCookies.get(IC_WEB_TOKEN);
    const userId = req.universalCookies.get(exports.IC_USER_ID);
    if (webtoken !== undefined && userId !== undefined) {
        console.log("webtoken: ", webtoken);
        console.log("userId: ", userId);
        try {
            const decoded = jsonwebtoken_1.default.verify(webtoken, clientSecret);
            if (decoded !== undefined) {
                const { id } = decoded;
                console.log("id: ", id);
                // we might have numbers... then the "===" comparison does not work
                if (id.toString() === userId.toString()) {
                    // the token contains the correct id
                    console.log("token matches :-)");
                    onAuthenticated(id.toString());
                    return next();
                }
            }
            return next("UserId in Token does not match UserId in cookie");
            //throw new Error("UserId in Token does not match UserId in cookie");
        }
        catch (err) {
            return next(err);
            //throw new Error(err);
        }
    }
    else {
        return next('No token present!');
        //throw new Error('No token present!');
    }
};
/**
 * Use this middleware at the endpoint that is specified as the callback-url.
 *
 * @param fetchAccessToken function that can be called to fetch the access Token
 * @param getUserData function to get the userData, takes as input the response from the accessToken-request
 * @param clientSecret
 * @param callbackUrl
 * @param storeAuthData
 * @returns {any}
 */
exports.createCallbackMiddleware = (clientSecret, fetchAccessToken, getUserData, storeAuthData) => function (req, res, next) {
    return __awaiter(this, void 0, void 0, function* () {
        const path = require('path');
        console.log("THIS IS THE AUTH CALLBACK");
        const { redirectPage, fFetch } = fetchAccessToken(req);
        // store the redirectPage in the request for further processing
        console.log("redirect to: ", redirectPage);
        req["redirectPage"] = redirectPage;
        yield fFetch().then(function (response) {
            return response.json();
        }).then(function (resJson) {
            return __awaiter(this, void 0, void 0, function* () {
                //const { token_type, access_token /*, refresh_token, scope, expires_at */} = resJson;
                // try the freshly acquired token and get the user's Medium.com id
                yield getUserData(resJson).then(function (data) {
                    return __awaiter(this, void 0, void 0, function* () {
                        //console.log(JSON.stringify(dataJson));
                        const { id, name, username, imageUrl, access_token } = data;
                        //console.log("id: ", id);
                        //console.log("name: ", name);
                        const today = new Date();
                        const expirationDate = new Date(today);
                        expirationDate.setDate(today.getDate() + 60);
                        // we use the clientSecret to sign the webtoken
                        const webtoken = jsonwebtoken_1.default.sign({
                            id: id,
                            exp: expirationDate.getTime() / 1000,
                        }, clientSecret);
                        // now let's use the webtoken to encrypt the access token
                        const encryptedAccessToken = jsonwebtoken_1.default.sign({
                            id: id,
                            accessToken: access_token,
                            exp: expirationDate.getTime() / 1000,
                        }, webtoken);
                        //console.log("encryptedAccessToken: ", encryptedAccessToken);
                        // TODO id may be undefined when the token expired!
                        //console.log("storeAuthData: ", storeAuthData)
                        // put the encrypted web token into the database, this is user (browser)-specific data!
                        const storeResult = yield storeAuthData(req, // request: any
                        exports.IC_USER_ID, // key: string
                        id, //val: any,
                        {
                            encryptedAccessToken: encryptedAccessToken
                        } //jsonData: any
                        );
                        console.log("storeResult: ", storeResult);
                        // give the webtoken to back to the user
                        req.universalCookies.set(IC_WEB_TOKEN, webtoken);
                        req.universalCookies.set(exports.IC_USER_ID, id);
                        console.log("done"); //'http://' +path.join(req.headers.host +  +
                        res.redirect(path.join(iso_libs_1.getBasename(), redirectPage));
                        return;
                    });
                });
            });
        });
    });
};
//# sourceMappingURL=auth-middleware.js.map