"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.useRequiredSSO = exports.RequiredSSO = exports.StrategyAvatar = exports.getLink = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
/*
 *  This file is part of CoCalc: Copyright © 2022 Sagemath, Inc.
 *  License: AGPLv3 s.t. "Commons Clause" – see LICENSE.md for details
 */
const icon_1 = require("@cocalc/frontend/components/icon");
const check_required_sso_1 = require("@cocalc/server/auth/sso/check-required-sso");
const passport_types_1 = require("@cocalc/util/types/passport-types");
const antd_1 = require("antd");
const loading_1 = __importDefault(require("components/share/loading"));
const base_path_1 = __importDefault(require("lib/base-path"));
const customize_1 = require("lib/customize");
const router_1 = require("next/router");
const path_1 = require("path");
const react_1 = require("react");
const { Link: AntdLink } = antd_1.Typography;
const sso_module_css_1 = __importDefault(require("./sso.module.css"));
function getLink(strategy, target) {
    // special case: private SSO mechanism, we point to the overview page
    if (strategy === "sso") {
        return `${(0, path_1.join)(base_path_1.default, "sso")}`;
    }
    // TODO: the target is ignored by the server right now -- it's not implemented
    // and I don't know how... yet.  Code is currently in src/packages/hub/auth.ts
    return `${(0, path_1.join)(base_path_1.default, "auth", strategy)}${target ? "?target=" + encodeURIComponent(target) : ""}`;
}
exports.getLink = getLink;
function SSO(props) {
    const { size, style, header } = props;
    const { strategies } = (0, customize_1.useCustomize)();
    const ssoHREF = useSSOHref("sso");
    const havePrivateSSO = (0, react_1.useMemo)(() => {
        return strategies?.some((s) => !s.public) ?? false;
    }, [strategies]);
    if (strategies == null) {
        return (0, jsx_runtime_1.jsx)(loading_1.default, { style: { fontSize: "16pt" } });
    }
    if (strategies.length == 0)
        return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, {});
    function renderPrivateSSO() {
        if (!havePrivateSSO)
            return;
        // a fake entry to point the user to the page for private SSO login options
        const sso = {
            name: "sso",
            display: "institutional Single Sign-On",
            icon: "api",
            backgroundColor: "",
            public: true,
            exclusiveDomains: [],
            doNotHide: true,
        };
        return ((0, jsx_runtime_1.jsxs)("a", { href: ssoHREF, children: ["Institutional Single Sign-On: ", (0, jsx_runtime_1.jsx)(StrategyAvatar, { strategy: sso, size: size ?? 60 }, "sso")] }));
    }
    function renderStrategies() {
        if (strategies == null)
            return;
        return strategies
            .filter((s) => s.public || s.doNotHide)
            .map((strategy) => ((0, jsx_runtime_1.jsx)(StrategyAvatar, { strategy: strategy, size: size ?? 60 }, strategy.name)));
    }
    // The -5px is to offset the initial avatar image, since they
    // all have a left margin.
    return ((0, jsx_runtime_1.jsxs)("div", { style: { ...style }, children: [header, (0, jsx_runtime_1.jsx)("div", { style: { marginLeft: "-5px" }, children: renderStrategies() }), (0, jsx_runtime_1.jsx)("div", { style: { marginLeft: "-5px", marginTop: "10px" }, children: renderPrivateSSO() })] }));
}
exports.default = SSO;
function useSSOHref(name) {
    const router = (0, router_1.useRouter)();
    if (name == null)
        return "";
    return getLink(name, (0, path_1.join)(router.basePath, router.pathname));
}
function StrategyAvatar(props) {
    const { strategy, size, noLink, toolTip, showName = false } = props;
    const { name, display, backgroundColor } = strategy;
    const icon = iconName();
    const ssoHREF = useSSOHref(name);
    const STYLE = {
        fontSize: `${size - 2}px`,
        color: backgroundColor ? "white" : "black",
        margin: "0 2px",
    };
    // this derives the name of the icon, that's shown on the avatar
    // in particular, the old public SSO mechanisms are special cases.
    function iconName() {
        // icon could be "null"
        if (strategy.icon != null)
            return strategy.icon;
        if (passport_types_1.PRIMARY_SSO.includes(strategy.name)) {
            return strategy.name;
        }
        return "link"; // a chain link, very general fallback
    }
    function renderIconImg() {
        if (icon?.includes("://")) {
            return ((0, jsx_runtime_1.jsx)("img", { src: icon, style: {
                    height: `${size - 2}px`,
                    width: `${size - 2}px`,
                    marginLeft: "2.5px",
                    objectFit: "contain",
                } }));
        }
        else {
            return (0, jsx_runtime_1.jsx)(icon_1.Icon, { name: icon, style: { ...STYLE, backgroundColor } });
        }
    }
    function renderAvatar() {
        const avatar = ((0, jsx_runtime_1.jsx)(antd_1.Avatar, { shape: "square", size: size, src: renderIconImg(), gap: 1, className: sso_module_css_1.default.icon }));
        if (noLink) {
            return avatar;
        }
        else {
            return (0, jsx_runtime_1.jsx)("a", { href: ssoHREF, children: avatar });
        }
    }
    function renderIcon() {
        if (icon?.includes("://"))
            return "";
        return ((0, jsx_runtime_1.jsx)(icon_1.Icon, { name: icon, style: { fontSize: "14pt", marginRight: "10px" } }));
    }
    function renderName() {
        if (!showName)
            return;
        return ((0, jsx_runtime_1.jsx)("div", { style: { textAlign: "center", whiteSpace: "nowrap" }, children: display }));
    }
    return ((0, jsx_runtime_1.jsx)(antd_1.Tooltip, { title: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [renderIcon(), " ", toolTip ?? (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Use your ", display, " account."] })] }), color: backgroundColor, children: (0, jsx_runtime_1.jsxs)("div", { style: { display: "inline-block" }, children: [renderAvatar(), renderName()] }) }));
}
exports.StrategyAvatar = StrategyAvatar;
function RequiredSSO({ strategy }) {
    if (strategy == null)
        return null;
    if (strategy.name == "null")
        return (0, jsx_runtime_1.jsx)(antd_1.Alert, { type: "error", message: "SSO Strategy not defined!" });
    const ssoLink = (0, path_1.join)(base_path_1.default, "sso", strategy.name);
    return ((0, jsx_runtime_1.jsx)(antd_1.Alert, { style: { margin: "15px 0" }, type: "warning", showIcon: false, message: `Single Sign-On required`, description: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("p", { children: ["You must sign up using the", " ", (0, jsx_runtime_1.jsx)(AntdLink, { strong: true, underline: true, href: ssoLink, children: strategy.display }), " ", "Single Sign-On strategy."] }), (0, jsx_runtime_1.jsx)("p", { style: { textAlign: "center" }, children: (0, jsx_runtime_1.jsx)(StrategyAvatar, { strategy: strategy, size: 120 }, strategy.name) })] }) }));
}
exports.RequiredSSO = RequiredSSO;
// based on (partially) entered email address.
// if user has to sign up via SSO, this will tell which strategy to use.
// this also checks for subdomains via a simple heuristic – the precise test is on the backend.
// hence this should be good enough to catch @email.foo.edu for foo.edu domains
function useRequiredSSO(strategies, email) {
    return (0, react_1.useMemo)(() => {
        return (0, check_required_sso_1.checkRequiredSSO)({ email, strategies });
    }, [strategies == null, email]);
}
exports.useRequiredSSO = useRequiredSSO;
//# sourceMappingURL=sso.js.map