CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
sagemathinc

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/next/components/auth/redeem-password-reset.tsx
Views: 687
1
/*
2
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
import { Alert, Button, Input } from "antd";
7
import { useState } from "react";
8
import { useRouter } from "next/router";
9
10
import useCustomize from "lib/use-customize";
11
import A from "components/misc/A";
12
import apiPost from "lib/api/post";
13
import { Icon } from "@cocalc/frontend/components/icon";
14
import Contact from "components/landing/contact";
15
16
import AuthPageContainer from "./fragments/auth-page-container";
17
18
export default function PasswordReset({ passwordResetId }) {
19
const { siteName } = useCustomize();
20
const [password, setPassword] = useState<string>("");
21
const [resetting, setResetting] = useState<boolean>(false);
22
const [error, setError] = useState<string>("");
23
const [success, setSuccess] = useState<string>("");
24
const router = useRouter();
25
26
async function resetPassword() {
27
if (resetting) return;
28
try {
29
setError("");
30
setSuccess("");
31
setResetting(true);
32
await apiPost("/auth/redeem-password-reset", {
33
password,
34
passwordResetId,
35
});
36
// if no error got signed in, so go to success page.
37
router.push("/auth/password-reset-done");
38
} catch (err) {
39
setError(`${err}`);
40
} finally {
41
setResetting(false);
42
}
43
}
44
45
function renderFooter() {
46
return (
47
<>
48
<p>
49
Remember your password? <A href="/auth/sign-in">Sign In</A>
50
</p>
51
You can also{" "}
52
<A href="/auth/try">use {siteName} without creating an account</A>
53
</>
54
);
55
}
56
57
function renderError() {
58
return error && (
59
<div style={{ fontSize: "12pt" }}>
60
<b>{error}</b>
61
<br/> If you are stuck, please <Contact lower/>.
62
</div>
63
);
64
}
65
66
return (
67
<AuthPageContainer
68
error={renderError()}
69
footer={renderFooter()}
70
title={`Reset Your ${siteName} Password`}
71
>
72
<div style={{ margin: "10px 0" }}>
73
Choose a new {siteName} password:
74
</div>
75
<form>
76
<Input.Password
77
style={{ fontSize: "13pt" }}
78
autoFocus
79
placeholder="New Password"
80
autoComplete="username"
81
value={password}
82
onChange={(e) => {
83
setPassword(e.target.value);
84
setError("");
85
setSuccess("");
86
}}
87
onPressEnter={(e) => {
88
e.preventDefault();
89
if (resetting || !isValidPassword(password)) return;
90
resetPassword();
91
}}
92
/>
93
<Button
94
disabled={!password || resetting || !isValidPassword(password)}
95
shape="round"
96
size="large"
97
type="primary"
98
style={{ width: "100%", marginTop: "20px" }}
99
onClick={resetPassword}
100
>
101
{resetting ? (
102
<>
103
<Icon name="spinner" spin/> Changing password...
104
</>
105
) : !isValidPassword(password) ? (
106
"Enter password (at least 6 characters)."
107
) : (
108
"Change Password"
109
)}
110
</Button>
111
</form>
112
{success && (
113
<Alert
114
style={{ marginTop: "20px" }}
115
message={<b>Success</b>}
116
description={<div style={{ fontSize: "12pt" }}>{success}</div>}
117
type="success"
118
showIcon
119
/>
120
)}
121
</AuthPageContainer>
122
);
123
}
124
125
function isValidPassword(password: string): boolean {
126
return password.length >= 6;
127
}
128
129