Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/src/packages/frontend/client/account.ts
Views: 687
/*1* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45import { callback } from "awaiting";6declare const $: any; // jQuery7import * as message from "@cocalc/util/message";8import { AsyncCall, WebappClient } from "./client";9import type { ApiKey } from "@cocalc/util/db-schema/api-keys";10import api from "./api";1112export class AccountClient {13private async_call: AsyncCall;14private client: WebappClient;15private create_account_lock: boolean = false;1617constructor(client: WebappClient) {18this.client = client;19this.async_call = client.async_call;20}2122private async call(message): Promise<any> {23return await this.async_call({24message,25allow_post: false, // never works or safe for account related functionality26timeout: 30, // 30s for all account stuff.27});28}2930public async create_account(opts: {31first_name?: string;32last_name?: string;33email_address?: string;34password?: string;35agreed_to_terms?: boolean;36usage_intent?: string;37get_api_key?: boolean; // if given, will create/get api token in response message38token?: string; // only required if an admin set the account creation token.39}): Promise<any> {40if (this.create_account_lock) {41// don't allow more than one create_account message at once -- see https://github.com/sagemathinc/cocalc/issues/118742return message.account_creation_failed({43reason: {44account_creation_failed:45"You are submitting too many requests to create an account; please wait a second.",46},47});48}4950try {51this.create_account_lock = true;52return await this.call(message.create_account(opts));53} finally {54setTimeout(() => (this.create_account_lock = false), 1500);55}56}5758public async delete_account(account_id: string): Promise<any> {59return await this.call(message.delete_account({ account_id }));60}6162public async sign_in(opts: {63email_address: string;64password: string;65remember_me?: boolean;66get_api_key?: boolean; // if given, will create/get api token in response message67}): Promise<any> {68return await this.async_call({69message: message.sign_in(opts),70error_event: false,71});72}7374public async cookies(mesg): Promise<void> {75const f = (cb) => {76const j = $.ajax({77url: mesg.url,78data: { id: mesg.id, set: mesg.set, get: mesg.get, value: mesg.value },79});80j.done(() => cb());81j.fail(() => cb("failed"));82};83await callback(f);84}8586public async sign_out(everywhere: boolean = false): Promise<void> {87await api("/accounts/sign-out", { all: everywhere });88delete this.client.account_id;89await this.call(message.sign_out({ everywhere }));90this.client.emit("signed_out");91}9293public async change_password(94currentPassword: string,95newPassword: string = "",96): Promise<void> {97await api("/accounts/set-password", { currentPassword, newPassword });98}99100public async change_email(101new_email_address: string,102password: string = "",103): Promise<void> {104if (this.client.account_id == null) {105throw Error("must be logged in");106}107const x = await this.call(108message.change_email_address({109account_id: this.client.account_id,110new_email_address,111password,112}),113);114if (x.error) {115throw Error(x.error);116}117}118119public async send_verification_email(120only_verify: boolean = true,121): Promise<void> {122const account_id = this.client.account_id;123if (!account_id) {124throw Error("must be signed in to an account");125}126const x = await this.call(127message.send_verification_email({128account_id,129only_verify,130}),131);132if (x.error) {133throw Error(x.error);134}135}136137// forgot password -- send forgot password request to server138public async forgot_password(email_address: string): Promise<void> {139const x = await this.call(140message.forgot_password({141email_address,142}),143);144if (x.error) {145throw Error(x.error);146}147}148149// forgot password -- send forgot password request to server150public async reset_forgot_password(151reset_code: string,152new_password: string,153): Promise<void> {154const resp = await this.call(155message.reset_forgot_password({156reset_code,157new_password,158}),159);160if (resp.error) {161throw Error(resp.error);162}163}164165// forget about a given passport authentication strategy for this user166public async unlink_passport(strategy: string, id: string): Promise<any> {167return await this.call(168message.unlink_passport({169strategy,170id,171}),172);173}174175// legacy api: getting, setting, deleting, etc., the api key for this account176public async api_key(177action: "get" | "delete" | "regenerate",178password: string,179): Promise<string> {180if (this.client.account_id == null) {181throw Error("must be logged in");182}183return (184await this.call(185message.api_key({186action,187password,188}),189)190).api_key;191}192193// new interface: getting, setting, editing, deleting, etc., the api keys for a project194public async api_keys(opts: {195action: "get" | "delete" | "create" | "edit";196password?: string;197name?: string;198id?: number;199expire?: Date;200}): Promise<ApiKey[] | undefined> {201if (this.client.account_id == null) {202throw Error("must be logged in");203}204// because message always uses id, so we have to use something else!205const opts2: any = { ...opts };206delete opts2.id;207opts2.key_id = opts.id;208return (await this.call(message.api_keys(opts2))).response;209}210}211212213