Skip to content

Commit

Permalink
feat: add change master key (#170)
Browse files Browse the repository at this point in the history
* feat: add change master key

* refetch account to update the new test encrypt value
  • Loading branch information
invisal authored Oct 12, 2023
1 parent 9e85f52 commit 5c5eb43
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 25 deletions.
8 changes: 6 additions & 2 deletions src/renderer/components/Stack/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ interface StackProps {
center?: boolean;
full?: boolean;
padding?: boolean;
spacing?: 'none' | 'md';
spacing?: 'none' | 'sm' | 'md';
}

export default memo(function Stack({
Expand All @@ -23,7 +23,11 @@ export default memo(function Stack({
vertical ? styles.vertical : undefined,
full ? styles.full : undefined,
padding ? styles.padding : undefined,
spacing === 'none' ? styles.spaceNone : undefined,
spacing === 'none'
? styles.spaceNone
: spacing === 'sm'
? styles.spaceSmall
: undefined,
]
.filter(Boolean)
.join(' ');
Expand Down
6 changes: 5 additions & 1 deletion src/renderer/components/Stack/styles.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,8 @@

.spaceNone {
gap: 0px;
}
}

.spaceSmall {
gap: 10px;
}
154 changes: 136 additions & 18 deletions src/renderer/screens/WelcomeScreen/SetupAccountCallout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import {
import PasswordField from 'renderer/components/PasswordField';
import { useCallback, useRef, useState } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faCheckCircle } from '@fortawesome/free-solid-svg-icons';
import { faCheckCircle, faSpinner } from '@fortawesome/free-solid-svg-icons';
import LinkButton from 'renderer/components/Button/LinkButton';
import ButtonGroup from 'renderer/components/ButtonGroup';

function SetupAccountNotLogin() {
return (
Expand Down Expand Up @@ -93,23 +94,25 @@ function SetupAccountNewMasterKey({ user }: { user: LoginUser }) {

<SetupMasterPasswordInstruction />

<PasswordField
autoFocus
placeholder="Master password"
value={password}
onChange={setPassword}
/>
<p></p>
<PasswordField
autoFocus
placeholder="Confirm master password"
value={confirmed}
onChange={setConfirmed}
/>
<p></p>
<Button primary onClick={onSetupPassword}>
Setup Master Password
</Button>
<Stack vertical spacing="sm">
<PasswordField
autoFocus
placeholder="Master password"
value={password}
onChange={setPassword}
/>

<PasswordField
autoFocus
placeholder="Confirm master password"
value={confirmed}
onChange={setConfirmed}
/>

<Button primary onClick={onSetupPassword}>
Setup Master Password
</Button>
</Stack>
</div>
);
}
Expand Down Expand Up @@ -153,6 +156,11 @@ function SetupAccountExistingMasterKey({ user }: { user: LoginUser }) {
placeholder="Master password"
value={password}
onChange={setPassword}
onKeyDown={(e) => {
if (e.key === 'Enter') {
onCheckMasterPassword();
}
}}
/>
<p></p>
<Button primary onClick={onCheckMasterPassword}>
Expand All @@ -162,7 +170,108 @@ function SetupAccountExistingMasterKey({ user }: { user: LoginUser }) {
);
}

function SetupAccountChangePassword({ onClose }: { onClose: () => void }) {
const { api, setMasterPassword: setPersistentPassword } = useAuth();
const { refetch } = useCurrentUser();
const [oldMasterPassword, setOldMasterPassword] = useState('');
const [confirmMasterPassword, setConfirmMasterPassword] = useState('');
const [masterPassword, setMasterPassword] = useState('');
const [loading, setLoading] = useState(false);
const [error, setError] = useState('');

const onChangePassword = useCallback(() => {
if (!masterPassword) {
setError('Please enter valid master password.');
return;
}

if (confirmMasterPassword !== masterPassword) {
setError('The password is not matched');
return;
}

setLoading(true);
api
.updateMasterPassword(masterPassword, oldMasterPassword)
.then((resp) => {
if (resp.status) {
setPersistentPassword(masterPassword);
refetch();
onClose();
} else {
setError(resp.error?.message ?? '');
}
setLoading(false);
})
.catch(() => setLoading(false));
}, [
setPersistentPassword,
oldMasterPassword,
confirmMasterPassword,
onClose,
setLoading,
refetch,
]);

return (
<div>
{error && (
<p style={{ color: 'var(--color-critical)' }}>
<strong>Error</strong>: {error}
</p>
)}

{loading && (
<p>
<FontAwesomeIcon icon={faSpinner} spin />
<span>&nbsp;Changing password...</span>
</p>
)}

<Stack vertical spacing="sm">
<PasswordField
autoFocus
placeholder="Old master password"
value={oldMasterPassword}
onChange={setOldMasterPassword}
/>

<PasswordField
placeholder="New Master password"
value={masterPassword}
onChange={setMasterPassword}
/>

<PasswordField
placeholder="Confirm master password"
value={confirmMasterPassword}
onChange={setConfirmMasterPassword}
/>

<ButtonGroup>
<Button primary onClick={onChangePassword} disabled={loading}>
Change Password
</Button>
<Button onClick={onClose}>Cancel</Button>
</ButtonGroup>
</Stack>
</div>
);
}

function SetupAccountComplete({ user }: { user: LoginUser }) {
const [showChangePassword, setShowChangePassword] = useState(false);

if (showChangePassword) {
return (
<SetupAccountChangePassword
onClose={() => {
setShowChangePassword(false);
}}
/>
);
}

return (
<Stack>
<div>
Expand All @@ -175,6 +284,15 @@ function SetupAccountComplete({ user }: { user: LoginUser }) {
<div>
<h2 style={{ marginBottom: '0.5rem' }}>Welcome, {user.name}</h2>
<p>Your account is secured with your master password.</p>

<ul>
<li>
<LinkButton
text="Change new master password"
onClick={() => setShowChangePassword(true)}
/>
</li>
</ul>
</div>
</Stack>
);
Expand Down
10 changes: 8 additions & 2 deletions src/renderer/screens/WelcomeScreen/styles.module.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
.calloutBackground {
background-color: #4158D0;
background-image: linear-gradient(43deg, #4158D0 0%, #C850C0 46%, #FFCC70 100%);
background-color: #4158d0;
background-image: linear-gradient(
43deg,
#4158d0 0%,
#c850c0 46%,
#ffcc70 100%
);
padding: 40px;
}

Expand Down Expand Up @@ -61,4 +66,5 @@
.footer {
border-top: 1px solid var(--color-border);
padding-top: 10px;
margin-top: 10px;
}
9 changes: 7 additions & 2 deletions src/renderer/utils/RemoteAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,14 @@ export default class RemoteAPI {
oldMasterPassword?: string,
) {
return (
await this.client.post('/v1/user/master_key', {
await this.client.post<{
status: boolean;
error?: {
message?: string;
};
}>('/v1/user/master_key', {
masterkey: newMasterPassword,
oldMasterPassword: oldMasterPassword,
old_masterkey: oldMasterPassword,
})
).data;
}
Expand Down

0 comments on commit 5c5eb43

Please sign in to comment.