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/account/settings/password-setting.tsx
Views: 687
/*1* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45import { Form, Input } from "antd";6import { join } from "path";7import { useIntl } from "react-intl";89import { Button, ButtonToolbar, Well } from "@cocalc/frontend/antd-bootstrap";10import {11Rendered,12useIsMountedRef,13useState,14} from "@cocalc/frontend/app-framework";15import {16A,17ErrorDisplay,18LabeledRow,19Saving,20} from "@cocalc/frontend/components";21import { appBasePath } from "@cocalc/frontend/customize/app-base-path";22import { labels } from "@cocalc/frontend/i18n";23import { webapp_client } from "@cocalc/frontend/webapp-client";2425interface State {26state: "view" | "edit" | "saving"; // view --> edit --> saving --> view27old_password: string;28new_password: string;29error: string;30}3132export const PasswordSetting: React.FC = () => {33const intl = useIntl();34const is_mounted = useIsMountedRef();3536const [state, set_state] = useState<State["state"]>("view");37const [old_password, set_old_password] = useState("");38const [new_password, set_new_password] = useState("");39const [error, set_error] = useState("");4041function reset(): void {42set_state("view");43set_error("");44set_old_password("");45set_new_password("");46}4748function change_password(): void {49reset();50set_state("edit");51}5253function cancel_editing(): void {54set_state("view");55set_old_password("");56set_new_password("");57}5859async function save_new_password(): Promise<void> {60set_state("saving");61try {62await webapp_client.account_client.change_password(63old_password,64new_password,65);66if (!is_mounted.current) return;67} catch (err) {68if (!is_mounted.current) return;69set_state("edit"), set_error(`Error changing password -- ${err}`);70return;71}72reset();73}7475function is_submittable(): boolean {76return !!(77new_password.length >= 6 &&78new_password &&79new_password !== old_password80);81}8283function render_change_button(): Rendered {84if (is_submittable()) {85return (86<Button onClick={save_new_password} bsStyle="success">87{intl.formatMessage(labels.account_password_change)}88</Button>89);90} else {91return (92<Button disabled bsStyle="success">93{intl.formatMessage(labels.account_password_change)}94</Button>95);96}97}9899function render_error(): Rendered {100if (error) {101return (102<>103<ErrorDisplay104error={error}105onClose={() => set_error("")}106style={{ marginTop: "15px" }}107/>108<A href={join(appBasePath, "auth/password-reset")}>109{intl.formatMessage(labels.account_password_forgot)}110</A>111</>112);113}114}115116function onFinish(): void {117if (is_submittable()) {118save_new_password();119}120}121122function render_edit(): Rendered {123return (124<Well style={{ marginTop: "3ex" }}>125<Form onFinish={onFinish}>126<Form.Item>127Current password{" "}128<span color="#888">129(leave blank if you have not set a password)130</span>131<Input.Password132autoFocus133type="password"134value={old_password}135placeholder="Current password"136onChange={(e) => set_old_password(e.target.value)}137/>138</Form.Item>139New password140{new_password.length < 6 ? " (at least 6 characters)" : undefined}141{new_password.length >= 6 && new_password == old_password142? " (different than old password)"143: undefined}144<Form.Item>145<Input.Password146type="password"147value={new_password}148placeholder="New password"149onChange={(e) => {150set_new_password(e.target.value);151}}152/>153</Form.Item>154</Form>155<ButtonToolbar>156{render_change_button()}157<Button onClick={cancel_editing}>Cancel</Button>158</ButtonToolbar>159{render_error()}160{render_saving()}161</Well>162);163}164165function render_saving(): Rendered {166if (state === "saving") {167return <Saving />;168}169}170171return (172<LabeledRow173label={intl.formatMessage(labels.account_password)}174style={{ marginBottom: "15px" }}175>176<div style={{ height: "30px" }}>177<Button178className="pull-right"179disabled={state !== "view"}180onClick={change_password}181>182{intl.formatMessage(labels.account_password_change)}...183</Button>184</div>185{state !== "view" ? render_edit() : undefined}186</LabeledRow>187);188};189190191