Skip to content

Commit 5c5eb43

Browse files
authored
feat: add change master key (#170)
* feat: add change master key * refetch account to update the new test encrypt value
1 parent 9e85f52 commit 5c5eb43

File tree

5 files changed

+162
-25
lines changed

5 files changed

+162
-25
lines changed

src/renderer/components/Stack/index.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ interface StackProps {
66
center?: boolean;
77
full?: boolean;
88
padding?: boolean;
9-
spacing?: 'none' | 'md';
9+
spacing?: 'none' | 'sm' | 'md';
1010
}
1111

1212
export default memo(function Stack({
@@ -23,7 +23,11 @@ export default memo(function Stack({
2323
vertical ? styles.vertical : undefined,
2424
full ? styles.full : undefined,
2525
padding ? styles.padding : undefined,
26-
spacing === 'none' ? styles.spaceNone : undefined,
26+
spacing === 'none'
27+
? styles.spaceNone
28+
: spacing === 'sm'
29+
? styles.spaceSmall
30+
: undefined,
2731
]
2832
.filter(Boolean)
2933
.join(' ');

src/renderer/components/Stack/styles.module.scss

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,8 @@
2323

2424
.spaceNone {
2525
gap: 0px;
26-
}
26+
}
27+
28+
.spaceSmall {
29+
gap: 10px;
30+
}

src/renderer/screens/WelcomeScreen/SetupAccountCallout.tsx

Lines changed: 136 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ import {
99
import PasswordField from 'renderer/components/PasswordField';
1010
import { useCallback, useRef, useState } from 'react';
1111
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
12-
import { faCheckCircle } from '@fortawesome/free-solid-svg-icons';
12+
import { faCheckCircle, faSpinner } from '@fortawesome/free-solid-svg-icons';
1313
import LinkButton from 'renderer/components/Button/LinkButton';
14+
import ButtonGroup from 'renderer/components/ButtonGroup';
1415

1516
function SetupAccountNotLogin() {
1617
return (
@@ -93,23 +94,25 @@ function SetupAccountNewMasterKey({ user }: { user: LoginUser }) {
9394

9495
<SetupMasterPasswordInstruction />
9596

96-
<PasswordField
97-
autoFocus
98-
placeholder="Master password"
99-
value={password}
100-
onChange={setPassword}
101-
/>
102-
<p></p>
103-
<PasswordField
104-
autoFocus
105-
placeholder="Confirm master password"
106-
value={confirmed}
107-
onChange={setConfirmed}
108-
/>
109-
<p></p>
110-
<Button primary onClick={onSetupPassword}>
111-
Setup Master Password
112-
</Button>
97+
<Stack vertical spacing="sm">
98+
<PasswordField
99+
autoFocus
100+
placeholder="Master password"
101+
value={password}
102+
onChange={setPassword}
103+
/>
104+
105+
<PasswordField
106+
autoFocus
107+
placeholder="Confirm master password"
108+
value={confirmed}
109+
onChange={setConfirmed}
110+
/>
111+
112+
<Button primary onClick={onSetupPassword}>
113+
Setup Master Password
114+
</Button>
115+
</Stack>
113116
</div>
114117
);
115118
}
@@ -153,6 +156,11 @@ function SetupAccountExistingMasterKey({ user }: { user: LoginUser }) {
153156
placeholder="Master password"
154157
value={password}
155158
onChange={setPassword}
159+
onKeyDown={(e) => {
160+
if (e.key === 'Enter') {
161+
onCheckMasterPassword();
162+
}
163+
}}
156164
/>
157165
<p></p>
158166
<Button primary onClick={onCheckMasterPassword}>
@@ -162,7 +170,108 @@ function SetupAccountExistingMasterKey({ user }: { user: LoginUser }) {
162170
);
163171
}
164172

173+
function SetupAccountChangePassword({ onClose }: { onClose: () => void }) {
174+
const { api, setMasterPassword: setPersistentPassword } = useAuth();
175+
const { refetch } = useCurrentUser();
176+
const [oldMasterPassword, setOldMasterPassword] = useState('');
177+
const [confirmMasterPassword, setConfirmMasterPassword] = useState('');
178+
const [masterPassword, setMasterPassword] = useState('');
179+
const [loading, setLoading] = useState(false);
180+
const [error, setError] = useState('');
181+
182+
const onChangePassword = useCallback(() => {
183+
if (!masterPassword) {
184+
setError('Please enter valid master password.');
185+
return;
186+
}
187+
188+
if (confirmMasterPassword !== masterPassword) {
189+
setError('The password is not matched');
190+
return;
191+
}
192+
193+
setLoading(true);
194+
api
195+
.updateMasterPassword(masterPassword, oldMasterPassword)
196+
.then((resp) => {
197+
if (resp.status) {
198+
setPersistentPassword(masterPassword);
199+
refetch();
200+
onClose();
201+
} else {
202+
setError(resp.error?.message ?? '');
203+
}
204+
setLoading(false);
205+
})
206+
.catch(() => setLoading(false));
207+
}, [
208+
setPersistentPassword,
209+
oldMasterPassword,
210+
confirmMasterPassword,
211+
onClose,
212+
setLoading,
213+
refetch,
214+
]);
215+
216+
return (
217+
<div>
218+
{error && (
219+
<p style={{ color: 'var(--color-critical)' }}>
220+
<strong>Error</strong>: {error}
221+
</p>
222+
)}
223+
224+
{loading && (
225+
<p>
226+
<FontAwesomeIcon icon={faSpinner} spin />
227+
<span>&nbsp;Changing password...</span>
228+
</p>
229+
)}
230+
231+
<Stack vertical spacing="sm">
232+
<PasswordField
233+
autoFocus
234+
placeholder="Old master password"
235+
value={oldMasterPassword}
236+
onChange={setOldMasterPassword}
237+
/>
238+
239+
<PasswordField
240+
placeholder="New Master password"
241+
value={masterPassword}
242+
onChange={setMasterPassword}
243+
/>
244+
245+
<PasswordField
246+
placeholder="Confirm master password"
247+
value={confirmMasterPassword}
248+
onChange={setConfirmMasterPassword}
249+
/>
250+
251+
<ButtonGroup>
252+
<Button primary onClick={onChangePassword} disabled={loading}>
253+
Change Password
254+
</Button>
255+
<Button onClick={onClose}>Cancel</Button>
256+
</ButtonGroup>
257+
</Stack>
258+
</div>
259+
);
260+
}
261+
165262
function SetupAccountComplete({ user }: { user: LoginUser }) {
263+
const [showChangePassword, setShowChangePassword] = useState(false);
264+
265+
if (showChangePassword) {
266+
return (
267+
<SetupAccountChangePassword
268+
onClose={() => {
269+
setShowChangePassword(false);
270+
}}
271+
/>
272+
);
273+
}
274+
166275
return (
167276
<Stack>
168277
<div>
@@ -175,6 +284,15 @@ function SetupAccountComplete({ user }: { user: LoginUser }) {
175284
<div>
176285
<h2 style={{ marginBottom: '0.5rem' }}>Welcome, {user.name}</h2>
177286
<p>Your account is secured with your master password.</p>
287+
288+
<ul>
289+
<li>
290+
<LinkButton
291+
text="Change new master password"
292+
onClick={() => setShowChangePassword(true)}
293+
/>
294+
</li>
295+
</ul>
178296
</div>
179297
</Stack>
180298
);

src/renderer/screens/WelcomeScreen/styles.module.scss

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
.calloutBackground {
2-
background-color: #4158D0;
3-
background-image: linear-gradient(43deg, #4158D0 0%, #C850C0 46%, #FFCC70 100%);
2+
background-color: #4158d0;
3+
background-image: linear-gradient(
4+
43deg,
5+
#4158d0 0%,
6+
#c850c0 46%,
7+
#ffcc70 100%
8+
);
49
padding: 40px;
510
}
611

@@ -61,4 +66,5 @@
6166
.footer {
6267
border-top: 1px solid var(--color-border);
6368
padding-top: 10px;
69+
margin-top: 10px;
6470
}

src/renderer/utils/RemoteAPI.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,14 @@ export default class RemoteAPI {
3434
oldMasterPassword?: string,
3535
) {
3636
return (
37-
await this.client.post('/v1/user/master_key', {
37+
await this.client.post<{
38+
status: boolean;
39+
error?: {
40+
message?: string;
41+
};
42+
}>('/v1/user/master_key', {
3843
masterkey: newMasterPassword,
39-
oldMasterPassword: oldMasterPassword,
44+
old_masterkey: oldMasterPassword,
4045
})
4146
).data;
4247
}

0 commit comments

Comments
 (0)