exports.id = 6911;
exports.ids = [6911];
exports.modules = {

/***/ 840336:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.getServerSettings = void 0;
var server_settings_1 = __webpack_require__(526177);
Object.defineProperty(exports, "getServerSettings", ({ enumerable: true, get: function () { return server_settings_1.getServerSettings; } }));
//# sourceMappingURL=index.js.map

/***/ }),

/***/ 946911:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {

"use strict";

/*
 *  This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
 *  License: AGPLv3 s.t. "Commons Clause" – see LICENSE.md for details
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.StripeClient = exports.Stripe = void 0;
const hof_1 = __webpack_require__(807108);
const awaiting_1 = __webpack_require__(862567);
const async_utils_1 = __webpack_require__(644181);
const message = __importStar(__webpack_require__(866976));
const upgrades_1 = __webpack_require__(874999);
const name_1 = __importDefault(__webpack_require__(676941));
const database_1 = __webpack_require__(207007);
const stripe_1 = __importDefault(__webpack_require__(476229));
exports.Stripe = stripe_1.default;
const private_1 = __importDefault(__webpack_require__(797877));
const connection_1 = __importDefault(__webpack_require__(578608));
const sales_tax_1 = __webpack_require__(515767);
const logger_1 = __importDefault(__webpack_require__(227554));
const logger = (0, logger_1.default)("stripe-client");
function get_string_field(mesg, name) {
    if (mesg == null)
        throw Error("invalid message; must not be null");
    const x = mesg[name];
    if (typeof x != "string")
        throw Error(`mesg[${name}] must be a string`);
    return x;
}
function get_nonnull_field(mesg, name) {
    if (mesg == null)
        throw Error("invalid message; must not be null");
    const x = mesg[name];
    if (x == null)
        throw Error(`mesg[${name}] must be defined`);
    return x;
}
class StripeClient {
    constructor(client) {
        if (!client.account_id) {
            throw Error("account_id must be specified");
        }
        if (!client.database) {
            // TODO: Importing this at the top level doesn't work with
            // next.js right now for some reason.   I'm sure this problem
            // will vanish when @cocalc/database melts away or is rewritten
            // in typescript...
            client.database = (0, database_1.db)();
        }
        // Set defaults for some attributes of client, in case not specified
        if (client.dbg == null) {
            client.dbg = (f) => {
                return (...args) => logger.debug(`Stripe(account_id=${client.account_id})`, f, ...args);
            };
        }
        if (client.push_to_client == null) {
            client.push_to_client = () => { }; // no op
        }
        if (client.error_to_client == null) {
            client.error_to_client = () => { }; // no op
        }
        if (client.assert_user_is_in_group == null) {
            client.assert_user_is_in_group = () => { }; // no op
        }
        this.client = client;
        this.get_customer_id = (0, hof_1.reuseInFlight)(this.get_customer_id.bind(this));
    }
    dbg(f) {
        return this.client.dbg(`stripe.${f}`);
    }
    // Returns the stripe customer id for this account from our database,
    // or undefined if there is no known stripe customer id.
    // Throws an error if something goes wrong.
    // If called multiple times simultaneously, only does one DB query.
    async get_customer_id() {
        //  If no customer info yet with stripe, then NOT an error; instead,
        //  customer_id is undefined (but will check every time in this case).
        const dbg = this.dbg("get_customer_id");
        dbg();
        if (this.stripe_customer_id != null) {
            dbg("using cached this.stripe_customer_id");
            return this.stripe_customer_id;
        }
        const account_id = this.client.account_id;
        if (account_id == null) {
            throw Error("You must be signed in to use billing related functions.");
        }
        dbg("getting stripe_customer_id from database...");
        const stripe_customer_id = await (0, async_utils_1.callback2)(this.client.database.get_stripe_customer_id, { account_id });
        if (stripe_customer_id != null) {
            // cache it, since it won't change.
            this.stripe_customer_id = stripe_customer_id;
        }
        return stripe_customer_id;
    }
    // Raise an exception if user is not yet registered with stripe.
    async need_customer_id() {
        this.dbg("need_customer_id")();
        const customer_id = await this.get_customer_id();
        if (customer_id == null) {
            throw Error("stripe customer not defined");
        }
        return customer_id;
    }
    async stripe_api_pager_options(mesg) {
        return {
            customer: await this.need_customer_id(),
            limit: mesg.limit,
            ending_before: mesg.ending_before,
            starting_after: mesg.starting_after,
        };
    }
    async get_customer(customer_id) {
        const dbg = this.dbg("get_customer");
        if (customer_id == null) {
            dbg("getting customer id");
            customer_id = await this.need_customer_id();
        }
        dbg("now getting stripe customer object");
        return await (await (0, connection_1.default)()).customers.retrieve(customer_id);
    }
    async handle_mesg(mesg) {
        try {
            if (mesg.event.slice(0, 7) != "stripe_") {
                throw Error("mesg event must start with stripe_");
            }
            const f = this[`mesg_${mesg.event.slice(7)}`];
            if (f == null) {
                throw Error(`no such message type ${mesg.event}`);
            }
            else {
                let resp = await f.bind(this)(mesg);
                if (resp == null) {
                    resp = {};
                }
                resp.id = mesg.id;
                this.client.push_to_client(resp);
            }
        }
        catch (err) {
            let error;
            if (err.stack != null) {
                error = err.stack.split("\n")[0];
            }
            else {
                error = `${err}`;
            }
            this.dbg("handle_mesg")("Error", error, err.stack);
            this.client.error_to_client({ id: mesg.id, error });
        }
    }
    async mesg_get_customer(_mesg) {
        const dbg = this.dbg("mesg_get_customer");
        dbg("get information from stripe: subscriptions, payment methods, etc.");
        // note -- we explicitly put the "publishable_key" property there...
        return message.stripe_customer({
            stripe_publishable_key: (await (0, connection_1.default)()).publishable_key,
            customer: await this.update_database(),
        });
    }
    async mesg_create_source(mesg) {
        const dbg = this.dbg("mesg_create_source");
        dbg("create a payment method (credit card) in stripe for this user");
        const token = get_string_field(mesg, "token");
        dbg("looking up customer");
        const customer_id = await this.get_customer_id();
        if (customer_id == null) {
            await this.create_new_stripe_customer_from_card_token(token);
        }
        else {
            await this.add_card_to_existing_stripe_customer(token);
        }
    }
    async create_new_stripe_customer_from_card_token(token) {
        const dbg = this.dbg("create_new_stripe_customer_from_card_token");
        dbg("create new stripe customer from card token");
        // Check user is not anonymous.  Our user interface never provides
        // anything stripe related to anon users.  However, an "abuser"
        // might still try to trigger this.  Anonymous accounts may be easier
        // to create, e.g., no captcha, so we want to limit their potential for damage.
        const { is_anonymous } = await (0, private_1.default)(this.client.account_id);
        if (is_anonymous) {
            throw Error("anonymous users are not allowed to create a stripe customer");
        }
        dbg("get identifying info about user");
        const r = await (0, async_utils_1.callback2)(this.client.database.get_account, {
            columns: ["email_address", "first_name", "last_name"],
            account_id: this.client.account_id,
        });
        const email = r.email_address;
        const description = (0, name_1.default)(r.first_name, r.last_name);
        dbg(`they are ${description} with email ${email}`);
        dbg("creating stripe customer");
        const x = {
            source: token,
            description,
            name: description,
            email,
            metadata: {
                account_id: this.client.account_id,
            },
        };
        const customer_id = (await (await (0, connection_1.default)()).customers.create(x))
            .id;
        dbg("success; now save customer_id to database");
        await (0, async_utils_1.callback2)(this.client.database.set_stripe_customer_id, {
            account_id: this.client.account_id,
            customer_id,
        });
        await this.update_database();
    }
    async add_card_to_existing_stripe_customer(token) {
        const dbg = this.dbg("add_card_to_existing_stripe_customer");
        dbg("add card to existing stripe customer");
        const customer_id = await this.need_customer_id();
        await (await (0, connection_1.default)()).customers.createSource(customer_id, { source: token });
        await this.update_database();
    }
    async mesg_delete_source(mesg) {
        const dbg = this.dbg("mesg_delete_source");
        dbg("delete a payment method for this user");
        const card_id = get_string_field(mesg, "card_id");
        const customer_id = await this.get_customer_id();
        if (customer_id == null)
            throw Error("no customer information so can't delete source");
        await (await (0, connection_1.default)()).customers.deleteSource(customer_id, card_id);
        await this.update_database();
    }
    async mesg_set_default_source(mesg) {
        const dbg = this.dbg("mesg_set_default_source");
        dbg("set a payment method for this user to be the default");
        const card_id = get_string_field(mesg, "card_id");
        const customer_id = await this.need_customer_id();
        dbg("now setting the default source in stripe");
        await (await (0, connection_1.default)()).customers.update(customer_id, {
            default_source: card_id,
        });
        await this.update_database();
    }
    // update_database queries stripe for customer record, stores
    // it in the database, and  returns the new customer record
    // if it exists
    async update_database() {
        this.dbg("update_database")();
        const customer_id = await this.get_customer_id();
        if (customer_id == null)
            return;
        return await (0, async_utils_1.callback2)(this.client.database.stripe_update_customer, {
            account_id: this.client.account_id,
            stripe: await (0, connection_1.default)(),
            customer_id,
        });
    }
    async mesg_update_source(mesg) {
        const dbg = this.dbg("mesg_update_source");
        dbg("modify a payment method");
        const card_id = get_string_field(mesg, "card_id");
        const info = get_nonnull_field(mesg, "info");
        await (await (0, connection_1.default)()).sources.update(card_id, info);
        await this.update_database();
    }
    async sales_tax(customer_id) {
        return await (0, sales_tax_1.stripe_sales_tax)(customer_id, this.dbg("sales_tax"));
    }
    async mesg_create_subscription(mesg) {
        const dbg = this.dbg("mesg_create_subscription");
        dbg("create a subscription for this user, using some billing method");
        const plan = get_string_field(mesg, "plan");
        const schema = (__webpack_require__(47896).PROJECT_UPGRADES.subscription)[plan.split("-")[0]];
        if (schema == null)
            throw Error(`unknown plan -- '${plan}'`);
        const customer_id = await this.need_customer_id();
        const quantity = mesg.quantity ? mesg.quantity : 1;
        dbg("determine applicable tax");
        const tax_percent = await this.sales_tax(customer_id);
        // CRITICAL regarding setting tax_percent below: if we don't just multiply by 100, since then sometimes
        // stripe comes back with an error like this
        //    "Error: Invalid decimal: 8.799999999999999; must contain at maximum two decimal places."
        const options = {
            customer: customer_id,
            payment_behavior: "error_if_incomplete",
            items: [{ quantity, plan }],
            coupon: mesg.coupon_id,
            cancel_at_period_end: schema.cancel_at_period_end,
            tax_percent: tax_percent
                ? Math.round(tax_percent * 100 * 100) / 100
                : undefined,
        };
        dbg("add customer subscription to stripe");
        await (await (0, connection_1.default)()).subscriptions.create(options);
        dbg("added subscription; now save info in our database about it...");
        await this.update_database();
        if (options.coupon != null) {
            dbg("add coupon to customer history");
            const { coupon, coupon_history } = await this.validate_coupon(options.coupon);
            // SECURITY NOTE: incrementing a counter... subject to attack?
            // I.e., use a coupon more times than should be able to?
            // NOT a big worry since we never issue or use coupons anyways...
            coupon_history[coupon.id] += 1;
            await (0, async_utils_1.callback2)(this.client.database.update_coupon_history, {
                account_id: this.client.account_id,
                coupon_history,
            });
        }
    }
    async mesg_cancel_subscription(mesg) {
        const dbg = this.dbg("mesg_cancel_subscription");
        dbg("cancel a subscription for this user");
        const subscription_id = get_string_field(mesg, "subscription_id");
        // TODO/SECURITY: We should check that this subscription actually
        // belongs to this user.  As it is, they could be cancelling somebody
        // else's subscription!
        dbg("cancel the subscription at stripe");
        await (await (0, connection_1.default)()).subscriptions.update(subscription_id, {
            cancel_at_period_end: mesg.at_period_end,
        });
        await this.update_database();
    }
    async mesg_update_subscription(mesg) {
        const dbg = this.dbg("mesg_update_subscription");
        dbg("edit a subscription for this user");
        const subscription_id = get_string_field(mesg, "subscription_id");
        dbg("Update the subscription.");
        const changes = {
            quantity: mesg.quantity,
            plan: mesg.plan,
            coupon: mesg.coupon_id,
        };
        await (await (0, connection_1.default)()).subscriptions.update(subscription_id, changes);
        await this.update_database();
        if (mesg.coupon_id != null) {
            const { coupon, coupon_history } = await this.validate_coupon(mesg.coupon_id);
            coupon_history[coupon.id] += 1;
            await (0, async_utils_1.callback2)(this.client.database.update_coupon_history, {
                account_id: this.client.account_id,
                coupon_history,
            });
        }
    }
    async mesg_get_subscriptions(mesg) {
        const dbg = this.dbg("mesg_get_subscriptions");
        dbg("get a list of all the subscriptions that this customer has");
        const options = await this.stripe_api_pager_options(mesg);
        options.status = "all";
        const subscriptions = await (await (0, connection_1.default)()).subscriptions.list(options);
        return message.stripe_subscriptions({ subscriptions });
    }
    async mesg_get_coupon(mesg) {
        const dbg = this.dbg("mesg_get_coupon");
        dbg(`get the coupon with id=${mesg.coupon_id}`);
        const coupon_id = get_string_field(mesg, "coupon_id");
        const { coupon } = await this.validate_coupon(coupon_id);
        return message.stripe_coupon({ coupon });
    }
    // Checks these coupon criteria:
    // - Exists
    // - Is valid
    // - Used by this account less than the max per account (hard coded default is 1)
    async validate_coupon(coupon_id) {
        const dbg = this.dbg("validate_coupon");
        dbg("retrieve the coupon");
        const coupon = await (await (0, connection_1.default)()).coupons.retrieve(coupon_id);
        dbg("check account coupon_history");
        let coupon_history = await (0, async_utils_1.callback2)(this.client.database.get_coupon_history, {
            account_id: this.client.account_id,
        });
        if (!coupon.valid)
            throw Error("Sorry! This coupon has expired.");
        if (coupon_history == null) {
            coupon_history = {};
        }
        const times_used = coupon_history[coupon.id] != null ? coupon_history[coupon.id] : 0;
        if (times_used >=
            (coupon.metadata.max_per_account != null
                ? coupon.metadata.max_per_account
                : 1)) {
            throw Error("You've already used this coupon.");
        }
        coupon_history[coupon.id] = times_used;
        return { coupon, coupon_history };
    }
    async mesg_get_charges(mesg) {
        const dbg = this.dbg("mesg_get_charges");
        dbg("get a list of charges for this customer");
        const options = await this.stripe_api_pager_options(mesg);
        const charges = await (await (0, connection_1.default)()).charges.list(options);
        return message.stripe_charges({ charges });
    }
    async mesg_get_invoices(mesg) {
        const dbg = this.dbg("mesg_get_invoices");
        dbg("get a list of invoices for this customer");
        const options = await this.stripe_api_pager_options(mesg);
        const invoices = await (await (0, connection_1.default)()).invoices.list(options);
        return message.stripe_invoices({ invoices });
    }
    // This is not actually used **YET**.
    async mesg_admin_create_invoice_item(mesg) {
        const dbg = this.dbg("mesg_admin_create_invoice_item");
        dbg();
        await (0, awaiting_1.callback)(this.client.assert_user_is_in_group.bind(this.client), "admin");
        dbg("check for existing stripe customer_id");
        const r = await (0, async_utils_1.callback2)(this.client.database.get_account, {
            columns: [
                "stripe_customer_id",
                "email_address",
                "first_name",
                "last_name",
                "account_id",
            ],
            account_id: mesg.account_id,
            email_address: mesg.email_address,
        });
        let customer_id = r.stripe_customer_id;
        const email = r.email_address;
        const description = (0, name_1.default)(r.first_name, r.last_name);
        mesg.account_id = r.account_id;
        const conn = await (0, connection_1.default)();
        if (customer_id != null) {
            dbg("already signed up for stripe -- sync local user account with stripe");
            await (0, async_utils_1.callback2)(this.client.database.stripe_update_customer, {
                account_id: mesg.account_id,
                stripe: conn,
                customer_id,
            });
        }
        else {
            dbg("create stripe entry for this customer");
            const { is_anonymous } = await (0, private_1.default)(mesg.account_id);
            if (is_anonymous) {
                throw Error("anonymous users are not allowed to create a stripe customer");
            }
            const x = {
                description,
                email,
                metadata: {
                    account_id: mesg.account_id,
                },
            };
            const customer = await conn.customers.create(x);
            customer_id = customer.id;
            dbg("store customer id in our database");
            await (0, async_utils_1.callback2)(this.client.database.set_stripe_customer_id, {
                account_id: mesg.account_id,
                customer_id,
            });
        }
        if (!(mesg.amount != null && mesg.description != null)) {
            dbg("no amount or no description, so not creating an invoice");
            return;
        }
        dbg("now create the invoice item");
        await conn.invoiceItems.create({
            customer: customer_id,
            amount: mesg.amount * 100,
            currency: "usd",
            description: mesg.description,
        });
    }
    async mesg_get_available_upgrades(_mesg) {
        const dbg = this.dbg("mesg_get_available_upgrades");
        dbg("get stripe customer data");
        const customer = await this.get_customer();
        if (customer == null || customer.subscriptions == null) {
            // no upgrades since not even a stripe account.
            return message.available_upgrades({
                total: {},
                excess: {},
                available: {},
            });
        }
        const stripe_data = customer.subscriptions.data;
        dbg("get user project upgrades");
        const projects = await (0, async_utils_1.callback2)(this.client.database.get_user_project_upgrades, {
            account_id: this.client.account_id,
        });
        const { excess, available } = (0, upgrades_1.available_upgrades)(stripe_data, projects);
        const total = (0, upgrades_1.get_total_upgrades)(stripe_data);
        return message.available_upgrades({
            total,
            excess,
            available,
        });
    }
    async mesg_remove_all_upgrades(mesg) {
        const dbg = this.dbg("mesg_remove_all_upgrades");
        dbg();
        if (this.client.account_id == null)
            throw Error("you must be signed in");
        await (0, async_utils_1.callback2)(this.client.database.remove_all_user_project_upgrades, {
            account_id: this.client.account_id,
            projects: mesg.projects,
        });
    }
    async mesg_sync_site_license_subscriptions() {
        const dbg = this.dbg("mesg_sync_site_license_subscriptions");
        dbg();
        if (this.client.account_id == null)
            throw Error("you must be signed in");
        await this.client.database.sync_site_license_subscriptions(this.client.account_id);
    }
    async cancelEverything() {
        const dbg = this.dbg("cancelEverything");
        const customer_id = await this.get_customer_id();
        dbg("customer_id = ", customer_id);
        if (customer_id == null) {
            // nothing to do, since no stripe info about this user.
            return;
        }
        const conn = await (0, connection_1.default)();
        dbg("Cancel the credit cards");
        const customer = await this.get_customer(customer_id);
        const payment_methods = customer.sources?.data;
        if (payment_methods != null) {
            for (const { id } of payment_methods) {
                await conn.customers.deleteSource(customer_id, id);
            }
        }
        dbg("Cancel the subscriptions (at period end)");
        const subscriptions = customer.subscriptions?.data;
        if (subscriptions != null) {
            for (const { id } of subscriptions) {
                await conn.subscriptions.update(id, {
                    cancel_at_period_end: true,
                });
            }
        }
        dbg("Sync the database to indicate that everything is canceled.");
        await this.update_database();
    }
    async getPaymentMethods() {
        const dbg = this.dbg("get_sources");
        dbg("get a list of all the payment sources that this customer has");
        const customer = await this.need_customer_id();
        const conn = await (0, connection_1.default)();
        await conn.paymentMethods.list({ customer, type: "card" });
    }
    async setDefaultSource(default_source) {
        const conn = await (0, connection_1.default)();
        await conn.customers.update(await this.need_customer_id(), {
            default_source,
        });
        await this.update_database();
    }
    async deletePaymentMethod(id) {
        const conn = await (0, connection_1.default)();
        await conn.customers.deleteSource(await this.need_customer_id(), id);
        await this.update_database();
    }
    async createPaymentMethod(token) {
        await this.mesg_create_source({ token });
    }
    async cancelSubscription(id) {
        // TODO/SECURITY: see comment in mesg_cancel_subscription
        const conn = await (0, connection_1.default)();
        await conn.subscriptions.update(id, { cancel_at_period_end: true });
        await this.update_database();
    }
}
exports.StripeClient = StripeClient;
//# sourceMappingURL=client.js.map

/***/ }),

/***/ 578608:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {

"use strict";

/*
 *  This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
 *  License: AGPLv3 s.t. "Commons Clause" – see LICENSE.md for details
 */
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
/*
The stripe connection object, which communicates with the remote stripe server.

Configure via the admin panel in account settings of an admin user.

Throws an error if stripe is not configured.

Double checks with database once per minute to see if the keys have changed,
and if so will return new stripe object.
*/
const stripe_1 = __importDefault(__webpack_require__(476229));
const settings_1 = __webpack_require__(840336);
// See https://stripe.com/docs/api/versioning
const apiVersion = "2020-03-02";
let stripe = undefined;
let key = "";
let last = 0;
async function getConn() {
    if (stripe != null && new Date().valueOf() - last <= 1000 * 60) {
        return stripe;
    }
    const { stripe_publishable_key, stripe_secret_key } = await (0, settings_1.getServerSettings)();
    if (!stripe_publishable_key) {
        throw Error("stripe publishable key is not set -- billing functionality not available");
    }
    if (!stripe_secret_key) {
        throw Error("stripe secret key is not set -- billing functionality not available");
    }
    if (stripe == null || key != stripe_publishable_key + stripe_secret_key) {
        key = stripe_publishable_key + stripe_secret_key;
        stripe = new stripe_1.default(stripe_secret_key, {
            apiVersion,
        });
        stripe.publishable_key = stripe_publishable_key;
        last = new Date().valueOf();
    }
    return stripe;
}
exports["default"] = getConn;
//# sourceMappingURL=connection.js.map

/***/ }),

/***/ 515767:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {

"use strict";

/*
 *  This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
 *  License: AGPLv3 s.t. "Commons Clause" – see LICENSE.md for details
 */
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.stripe_sales_tax = void 0;
/*
Compute sales tax for a given customer in WA state.
*/
const sales_tax_1 = __importDefault(__webpack_require__(853307));
const connection_1 = __importDefault(__webpack_require__(578608));
async function stripe_sales_tax(customer_id, dbg) {
    const conn = await (0, connection_1.default)();
    const customer = await conn.customers.retrieve(customer_id);
    if (customer.deleted) {
        // mainly have this check so Typescript is happy
        dbg("customer was deleted");
        return 0;
    }
    if (customer.default_source == null) {
        dbg("no default source");
        return 0;
    }
    let zip = undefined;
    if (customer.sources != null) {
        for (const x of customer.sources.data) {
            if (x.id == customer.default_source) {
                zip = x.address_zip?.slice(0, 5); // as any due to bug in Stripe's types
                break;
            }
        }
    }
    if (zip == null) {
        return 0;
    }
    const tax = (0, sales_tax_1.default)(zip);
    dbg("tax: ", tax);
    return tax;
}
exports.stripe_sales_tax = stripe_sales_tax;
//# sourceMappingURL=sales-tax.js.map

/***/ }),

/***/ 676941:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

Object.defineProperty(exports, "__esModule", ({ value: true }));
const misc_1 = __webpack_require__(854006);
function stripeName(firstName, lastName) {
    return (0, misc_1.trunc_middle)(`${firstName ?? ""} ${lastName ?? ""}`, 200);
}
exports["default"] = stripeName;
//# sourceMappingURL=name.js.map

/***/ }),

/***/ 853307:
/***/ ((__unused_webpack_module, exports) => {

"use strict";

/*
Sales tax for WA state.

Of course, this shouldn't exist much longer, since it's the sort of thing
that stripe automates.
*/
Object.defineProperty(exports, "__esModule", ({ value: true }));
// WA state sales tax rates, as of July 11 2017.
// Generated via scripts/sales_tax.py
function salesTax(zip) {
    return WA_sales_tax[zip] ?? 0;
}
exports["default"] = salesTax;
const WA_sales_tax = {
    98001: 0.099,
    98002: 0.086,
    98003: 0.1,
    98004: 0.1,
    98005: 0.1,
    98006: 0.086,
    98007: 0.1,
    98008: 0.1,
    98009: 0.1,
    98010: 0.086,
    98011: 0.1,
    98012: 0.077,
    98013: 0.086,
    98014: 0.086,
    98015: 0.1,
    98019: 0.077,
    98020: 0.1,
    98021: 0.077,
    98022: 0.079,
    98023: 0.1,
    98024: 0.086,
    98025: 0.086,
    98026: 0.1,
    98027: 0.086,
    98028: 0.1,
    98029: 0.086,
    98030: 0.1,
    98031: 0.1,
    98032: 0.1,
    98033: 0.1,
    98034: 0.1,
    98035: 0.1,
    98036: 0.103,
    98037: 0.103,
    98038: 0.086,
    98039: 0.1,
    98040: 0.1,
    98041: 0.1,
    98042: 0.086,
    98043: 0.1,
    98045: 0.086,
    98046: 0.104,
    98047: 0.093,
    98050: 0.086,
    98051: 0.086,
    98052: 0.086,
    98053: 0.086,
    98054: 0.086,
    98055: 0.1,
    98056: 0.1,
    98057: 0.1,
    98058: 0.086,
    98059: 0.086,
    98061: 0.09,
    98062: 0.1,
    98063: 0.1,
    98064: 0.1,
    98065: 0.086,
    98068: 0.08,
    98070: 0.086,
    98071: 0.1,
    98072: 0.077,
    98073: 0.1,
    98074: 0.086,
    98075: 0.086,
    98077: 0.077,
    98082: 0.104,
    98083: 0.1,
    98087: 0.103,
    98089: 0.1,
    98092: 0.086,
    98093: 0.1,
    98101: 0.101,
    98102: 0.101,
    98103: 0.101,
    98104: 0.101,
    98105: 0.101,
    98106: 0.1,
    98107: 0.101,
    98108: 0.1,
    98109: 0.101,
    98110: 0.09,
    98111: 0.101,
    98112: 0.101,
    98113: 0.101,
    98114: 0.101,
    98115: 0.101,
    98116: 0.101,
    98117: 0.101,
    98118: 0.101,
    98119: 0.101,
    98121: 0.101,
    98122: 0.101,
    98124: 0.101,
    98125: 0.1,
    98126: 0.1,
    98127: 0.101,
    98129: 0.101,
    98131: 0.1,
    98132: 0.1,
    98133: 0.1,
    98134: 0.101,
    98136: 0.101,
    98138: 0.1,
    98139: 0.101,
    98141: 0.101,
    98144: 0.1,
    98145: 0.101,
    98146: 0.1,
    98148: 0.1,
    98151: 0.1,
    98154: 0.101,
    98155: 0.1,
    98158: 0.1,
    98160: 0.1,
    98161: 0.101,
    98164: 0.101,
    98165: 0.101,
    98166: 0.1,
    98168: 0.1,
    98170: 0.1,
    98171: 0.1,
    98174: 0.101,
    98175: 0.101,
    98177: 0.1,
    98178: 0.1,
    98181: 0.101,
    98184: 0.101,
    98185: 0.101,
    98188: 0.1,
    98189: 0.1,
    98190: 0.1,
    98191: 0.101,
    98194: 0.101,
    98195: 0.101,
    98198: 0.1,
    98199: 0.101,
    98201: 0.089,
    98203: 0.077,
    98204: 0.097,
    98205: 0.097,
    98206: 0.097,
    98207: 0.097,
    98208: 0.077,
    98213: 0.097,
    98220: 0.085,
    98221: 0.081,
    98222: 0.081,
    98223: 0.077,
    98224: 0.086,
    98225: 0.079,
    98226: 0.079,
    98227: 0.087,
    98228: 0.087,
    98229: 0.079,
    98230: 0.079,
    98231: 0.085,
    98232: 0.085,
    98233: 0.081,
    98235: 0.085,
    98236: 0.087,
    98237: 0.079,
    98238: 0.081,
    98239: 0.087,
    98240: 0.085,
    98241: 0.081,
    98243: 0.081,
    98244: 0.079,
    98245: 0.081,
    98247: 0.085,
    98248: 0.079,
    98249: 0.087,
    98250: 0.081,
    98251: 0.086,
    98252: 0.077,
    98253: 0.087,
    98255: 0.085,
    98256: 0.089,
    98257: 0.081,
    98258: 0.077,
    98259: 0.091,
    98260: 0.087,
    98261: 0.081,
    98262: 0.079,
    98263: 0.085,
    98264: 0.085,
    98266: 0.085,
    98267: 0.085,
    98270: 0.077,
    98271: 0.077,
    98272: 0.077,
    98273: 0.081,
    98274: 0.081,
    98275: 0.097,
    98276: 0.085,
    98277: 0.087,
    98278: 0.087,
    98279: 0.081,
    98280: 0.081,
    98281: 0.079,
    98282: 0.077,
    98283: 0.079,
    98284: 0.077,
    98286: 0.081,
    98287: 0.089,
    98288: 0.086,
    98290: 0.077,
    98291: 0.091,
    98292: 0.077,
    98293: 0.089,
    98294: 0.077,
    98295: 0.085,
    98296: 0.077,
    98297: 0.081,
    98303: 0.079,
    98304: 0.078,
    98305: 0.084,
    98310: 0.085,
    98311: 0.09,
    98312: 0.085,
    98314: 0.09,
    98315: 0.09,
    98320: 0.085,
    98321: 0.079,
    98322: 0.09,
    98323: 0.079,
    98324: 0.084,
    98325: 0.09,
    98326: 0.084,
    98327: 0.079,
    98328: 0.079,
    98329: 0.079,
    98330: 0.078,
    98331: 0.084,
    98332: 0.079,
    98333: 0.079,
    98335: 0.079,
    98336: 0.078,
    98337: 0.09,
    98338: 0.079,
    98339: 0.09,
    98340: 0.09,
    98342: 0.09,
    98343: 0.084,
    98344: 0.079,
    98345: 0.09,
    98346: 0.09,
    98348: 0.079,
    98349: 0.079,
    98350: 0.084,
    98351: 0.079,
    98352: 0.093,
    98353: 0.09,
    98354: 0.099,
    98355: 0.078,
    98356: 0.078,
    98357: 0.084,
    98358: 0.09,
    98359: 0.079,
    98360: 0.079,
    98361: 0.078,
    98362: 0.084,
    98363: 0.084,
    98364: 0.09,
    98365: 0.09,
    98366: 0.09,
    98367: 0.09,
    98368: 0.09,
    98370: 0.09,
    98371: 0.099,
    98372: 0.093,
    98373: 0.093,
    98374: 0.093,
    98375: 0.093,
    98376: 0.09,
    98377: 0.078,
    98378: 0.09,
    98380: 0.085,
    98381: 0.084,
    98382: 0.084,
    98383: 0.09,
    98384: 0.09,
    98385: 0.079,
    98386: 0.09,
    98387: 0.079,
    98388: 0.079,
    98390: 0.093,
    98391: 0.079,
    98392: 0.09,
    98393: 0.09,
    98394: 0.079,
    98395: 0.079,
    98396: 0.079,
    98397: 0.079,
    98398: 0.079,
    98401: 0.101,
    98402: 0.099,
    98403: 0.101,
    98404: 0.099,
    98405: 0.093,
    98406: 0.093,
    98407: 0.099,
    98408: 0.099,
    98409: 0.099,
    98411: 0.101,
    98412: 0.101,
    98413: 0.101,
    98415: 0.101,
    98416: 0.101,
    98417: 0.101,
    98418: 0.101,
    98419: 0.101,
    98421: 0.099,
    98422: 0.099,
    98424: 0.099,
    98430: 0.093,
    98431: 0.093,
    98433: 0.093,
    98438: 0.093,
    98439: 0.093,
    98442: 0.093,
    98443: 0.099,
    98444: 0.093,
    98445: 0.093,
    98446: 0.079,
    98447: 0.099,
    98448: 0.099,
    98450: 0.099,
    98455: 0.099,
    98460: 0.099,
    98464: 0.099,
    98465: 0.099,
    98466: 0.099,
    98467: 0.099,
    98471: 0.101,
    98477: 0.101,
    98481: 0.101,
    98490: 0.101,
    98492: 0.101,
    98493: 0.099,
    98496: 0.099,
    98497: 0.099,
    98498: 0.093,
    98499: 0.093,
    98501: 0.079,
    98502: 0.079,
    98503: 0.087,
    98504: 0.088,
    98505: 0.087,
    98506: 0.079,
    98507: 0.088,
    98508: 0.088,
    98509: 0.089,
    98511: 0.089,
    98512: 0.079,
    98513: 0.079,
    98516: 0.079,
    98520: 0.088,
    98522: 0.078,
    98524: 0.085,
    98526: 0.088,
    98527: 0.08,
    98528: 0.079,
    98530: 0.079,
    98531: 0.078,
    98532: 0.078,
    98533: 0.078,
    98535: 0.088,
    98536: 0.088,
    98537: 0.08,
    98538: 0.078,
    98539: 0.078,
    98540: 0.079,
    98541: 0.085,
    98542: 0.078,
    98544: 0.078,
    98546: 0.085,
    98547: 0.08,
    98548: 0.085,
    98550: 0.088,
    98552: 0.088,
    98554: 0.08,
    98555: 0.085,
    98556: 0.079,
    98557: 0.085,
    98558: 0.079,
    98559: 0.088,
    98560: 0.085,
    98561: 0.08,
    98562: 0.088,
    98563: 0.085,
    98564: 0.078,
    98565: 0.078,
    98566: 0.088,
    98568: 0.078,
    98569: 0.088,
    98570: 0.078,
    98571: 0.088,
    98572: 0.078,
    98575: 0.088,
    98576: 0.079,
    98577: 0.08,
    98579: 0.078,
    98580: 0.079,
    98581: 0.078,
    98582: 0.078,
    98583: 0.088,
    98584: 0.085,
    98585: 0.078,
    98586: 0.08,
    98587: 0.088,
    98588: 0.085,
    98589: 0.079,
    98590: 0.08,
    98591: 0.078,
    98592: 0.085,
    98593: 0.078,
    98595: 0.088,
    98596: 0.078,
    98597: 0.079,
    98599: 0.088,
    98601: 0.077,
    98602: 0.07,
    98603: 0.078,
    98604: 0.077,
    98605: 0.07,
    98606: 0.077,
    98607: 0.077,
    98609: 0.078,
    98610: 0.077,
    98611: 0.078,
    98612: 0.076,
    98613: 0.07,
    98614: 0.08,
    98616: 0.078,
    98617: 0.07,
    98619: 0.07,
    98620: 0.07,
    98621: 0.076,
    98622: 0.077,
    98623: 0.07,
    98624: 0.08,
    98625: 0.078,
    98626: 0.078,
    98628: 0.07,
    98629: 0.077,
    98631: 0.08,
    98632: 0.076,
    98635: 0.07,
    98637: 0.08,
    98638: 0.076,
    98639: 0.077,
    98640: 0.08,
    98641: 0.08,
    98642: 0.077,
    98643: 0.076,
    98644: 0.08,
    98645: 0.078,
    98647: 0.076,
    98648: 0.077,
    98649: 0.078,
    98650: 0.07,
    98651: 0.077,
    98660: 0.077,
    98661: 0.084,
    98662: 0.077,
    98663: 0.084,
    98664: 0.084,
    98665: 0.084,
    98666: 0.084,
    98667: 0.084,
    98668: 0.084,
    98670: 0.07,
    98671: 0.077,
    98672: 0.07,
    98673: 0.07,
    98674: 0.077,
    98675: 0.077,
    98682: 0.077,
    98683: 0.084,
    98684: 0.084,
    98685: 0.077,
    98686: 0.077,
    98687: 0.084,
    98801: 0.082,
    98802: 0.082,
    98807: 0.084,
    98811: 0.082,
    98812: 0.078,
    98813: 0.077,
    98814: 0.081,
    98815: 0.082,
    98816: 0.081,
    98817: 0.082,
    98819: 0.081,
    98821: 0.082,
    98822: 0.082,
    98823: 0.078,
    98824: 0.079,
    98826: 0.082,
    98827: 0.081,
    98828: 0.082,
    98829: 0.081,
    98830: 0.077,
    98831: 0.082,
    98832: 0.079,
    98833: 0.081,
    98834: 0.081,
    98836: 0.082,
    98837: 0.079,
    98840: 0.077,
    98841: 0.077,
    98843: 0.078,
    98844: 0.081,
    98845: 0.078,
    98846: 0.081,
    98847: 0.082,
    98848: 0.078,
    98849: 0.081,
    98850: 0.078,
    98851: 0.079,
    98852: 0.082,
    98853: 0.079,
    98855: 0.081,
    98856: 0.081,
    98857: 0.077,
    98858: 0.078,
    98859: 0.081,
    98860: 0.079,
    98862: 0.081,
    98901: 0.079,
    98902: 0.081,
    98903: 0.079,
    98904: 0.079,
    98907: 0.082,
    98908: 0.079,
    98909: 0.081,
    98920: 0.079,
    98921: 0.079,
    98922: 0.08,
    98923: 0.079,
    98925: 0.08,
    98926: 0.08,
    98929: 0.08,
    98930: 0.079,
    98932: 0.079,
    98933: 0.079,
    98934: 0.08,
    98935: 0.07,
    98936: 0.079,
    98937: 0.078,
    98938: 0.079,
    98939: 0.079,
    98940: 0.08,
    98941: 0.08,
    98942: 0.079,
    98943: 0.08,
    98944: 0.079,
    98946: 0.08,
    98947: 0.079,
    98948: 0.079,
    98950: 0.08,
    98951: 0.079,
    98952: 0.079,
    98953: 0.079,
    99001: 0.088,
    99003: 0.081,
    99004: 0.081,
    99005: 0.081,
    99006: 0.076,
    99008: 0.08,
    99009: 0.076,
    99011: 0.088,
    99012: 0.081,
    99013: 0.076,
    99014: 0.088,
    99016: 0.081,
    99017: 0.078,
    99018: 0.081,
    99019: 0.081,
    99020: 0.081,
    99021: 0.081,
    99022: 0.081,
    99023: 0.081,
    99025: 0.081,
    99026: 0.076,
    99027: 0.081,
    99029: 0.08,
    99030: 0.081,
    99031: 0.081,
    99032: 0.077,
    99033: 0.078,
    99034: 0.076,
    99036: 0.081,
    99037: 0.081,
    99039: 0.081,
    99040: 0.076,
    99101: 0.076,
    99102: 0.078,
    99103: 0.079,
    99104: 0.078,
    99105: 0.077,
    99107: 0.077,
    99109: 0.076,
    99110: 0.076,
    99111: 0.078,
    99113: 0.078,
    99114: 0.076,
    99115: 0.078,
    99116: 0.077,
    99117: 0.08,
    99118: 0.077,
    99119: 0.076,
    99121: 0.077,
    99122: 0.076,
    99123: 0.079,
    99124: 0.077,
    99125: 0.077,
    99126: 0.076,
    99128: 0.078,
    99129: 0.076,
    99130: 0.078,
    99131: 0.076,
    99133: 0.078,
    99134: 0.08,
    99135: 0.079,
    99136: 0.078,
    99137: 0.076,
    99138: 0.077,
    99139: 0.076,
    99140: 0.077,
    99141: 0.076,
    99143: 0.078,
    99144: 0.08,
    99146: 0.077,
    99147: 0.08,
    99148: 0.076,
    99149: 0.078,
    99150: 0.077,
    99151: 0.076,
    99152: 0.076,
    99153: 0.076,
    99154: 0.08,
    99155: 0.077,
    99156: 0.076,
    99157: 0.076,
    99158: 0.078,
    99159: 0.077,
    99160: 0.077,
    99161: 0.078,
    99163: 0.078,
    99164: 0.078,
    99165: 0.078,
    99166: 0.077,
    99167: 0.076,
    99169: 0.077,
    99170: 0.078,
    99171: 0.078,
    99173: 0.076,
    99174: 0.078,
    99176: 0.078,
    99179: 0.078,
    99180: 0.076,
    99181: 0.076,
    99185: 0.08,
    99201: 0.088,
    99202: 0.088,
    99203: 0.081,
    99204: 0.088,
    99205: 0.081,
    99206: 0.081,
    99207: 0.088,
    99208: 0.081,
    99209: 0.088,
    99210: 0.088,
    99211: 0.088,
    99212: 0.081,
    99213: 0.088,
    99214: 0.088,
    99215: 0.088,
    99216: 0.081,
    99217: 0.081,
    99218: 0.081,
    99219: 0.088,
    99220: 0.088,
    99223: 0.081,
    99224: 0.081,
    99228: 0.088,
    99251: 0.088,
    99252: 0.088,
    99256: 0.088,
    99258: 0.088,
    99260: 0.088,
    99299: 0.088,
    99301: 0.08,
    99302: 0.086,
    99320: 0.08,
    99321: 0.079,
    99322: 0.07,
    99323: 0.081,
    99324: 0.087,
    99326: 0.077,
    99328: 0.081,
    99329: 0.081,
    99330: 0.08,
    99333: 0.078,
    99335: 0.08,
    99336: 0.08,
    99337: 0.08,
    99338: 0.08,
    99341: 0.077,
    99343: 0.08,
    99344: 0.077,
    99345: 0.08,
    99346: 0.08,
    99347: 0.079,
    99348: 0.081,
    99349: 0.079,
    99350: 0.07,
    99352: 0.08,
    99353: 0.08,
    99354: 0.086,
    99356: 0.07,
    99357: 0.079,
    99359: 0.081,
    99360: 0.081,
    99361: 0.081,
    99362: 0.081,
    99363: 0.081,
    99371: 0.077,
    99401: 0.077,
    99402: 0.077,
    99403: 0.079,
};
//# sourceMappingURL=sales-tax.js.map

/***/ }),

/***/ 874999:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

/*
 *  This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
 *  License: AGPLv3 s.t. "Commons Clause" – see LICENSE.md for details
 */
const { PROJECT_UPGRADES } = __webpack_require__(47896);
const misc = __webpack_require__(854006);
// This is used by the frontend in r_account.  It's also used by the backend
// to double check the claims of the frontend.
// stripe_subscriptions_data = stripe_customer?.subscriptions?.data
function get_total_upgrades(stripe_subscriptions_data) {
    const subs = stripe_subscriptions_data;
    if (subs == null) {
        return {};
    }
    // always running isn't in any of the subscriptions and I don't want to edit benefits
    // for all of them, so just put a zero 0 (since this whole old upgrades thing
    // will eventually go away). https://github.com/sagemathinc/cocalc/issues/4802
    let total = { always_running: 0 };
    for (let sub of subs) {
        if (sub.status != "active" && sub.status != "trialing") {
            // not yet paid for or no longer available.
            continue;
        }
        const info = PROJECT_UPGRADES.subscription[sub.plan.id.split("-")[0]];
        if (info == null) {
            // there are now some subscriptions that have nothing to do with "upgrades" (e.g., for licenses).
            continue;
        }
        const benefits = info.benefits;
        // TODO: add a quantity third field to map_sum to make this not so naive...
        for (let q = 0; q < sub.quantity; q++) {
            total = misc.map_sum(total, benefits);
        }
    }
    return total;
}
exports.get_total_upgrades = get_total_upgrades;
//
// INPUT:
//    subscriptions = {standard:2, premium:1, course:2, ...}
//    projects = {project_id:{cores:1, network:1, ...}, ...}
//
// OUTPUT:
//     {available:{cores:10, network:3, ...},   excess:{project_id:{cores:2, ...}}  }
//
function available_upgrades(stripe_subscriptions_data, projects) {
    let project_id, upgrades;
    const available = get_total_upgrades(stripe_subscriptions_data); // start with amount available being your quota
    const excess = {}; // nothing exceeds quota
    // sort projects by project_id so that excess will be well defined
    const v = [];
    for (project_id in projects) {
        upgrades = projects[project_id];
        v.push({ project_id, upgrades });
    }
    v.sort((a, b) => misc.cmp(a.project_id, b.project_id));
    for ({ project_id, upgrades } of v) {
        for (let prop in upgrades) {
            const curval = upgrades[prop];
            if (available[prop] == null) {
                available[prop] = 0;
            } // ensure that available is defined for this prop
            if (curval <= available[prop]) {
                // if the current value for this project is within what is left, just subtract it off
                available[prop] -= curval;
            }
            else {
                // otherwise, it goes over, so record by how much in excess, then set available to 0.
                if (excess[project_id] == null) {
                    excess[project_id] = {};
                }
                excess[project_id][prop] = curval - available[prop];
                available[prop] = 0;
            }
        }
    }
    return { available, excess };
}
exports.available_upgrades = available_upgrades;
// INPUT: same as above, but also a single project_id
//
// OUTPUT:  Returns the maximum amount for each upgrade setting that a control
// (which starts at 0) for configuring that setting for the project should go up to.
//
//      {cores:2, network:1, disk_quota:2000, memory:1000}
//
//
function upgrade_maxes(stripe_subscriptions_data, projects, project_id) {
    const { available, excess } = available_upgrades(stripe_subscriptions_data, projects);
    const allocated = projects[project_id];
    const maxes = {};
    for (let param in available) {
        const avail = available[param];
        const max = PROJECT_UPGRADES.max_per_project[param]; // the maximum allowed for this param for any project
        const alloc = allocated[param] != null ? allocated[param] : 0; // how much has already been allocated to this project
        maxes[param] = Math.min(alloc + avail, max);
    }
    return maxes;
}
exports.upgrade_maxes = upgrade_maxes;
//# sourceMappingURL=upgrades.js.map

/***/ })

};
;