mirror of
https://github.com/balzack/databag.git
synced 2025-02-14 04:29:17 +00:00
invoke mfa in browser
This commit is contained in:
parent
19248eee7c
commit
e5fe393b43
@ -35,6 +35,7 @@ func GetAccountStatus(w http.ResponseWriter, r *http.Request) {
|
||||
status.Disabled = account.Disabled
|
||||
status.ForwardingAddress = account.Forward
|
||||
status.Searchable = account.Searchable
|
||||
status.MFAEnabled = account.MFAEnabled && account.MFAConfirmed
|
||||
status.Sealable = true
|
||||
status.EnableIce = getBoolConfigValue(CNFEnableIce, false)
|
||||
status.AllowUnsealed = getBoolConfigValue(CNFAllowUnsealed, false)
|
||||
|
@ -35,6 +35,8 @@ type AccountStatus struct {
|
||||
|
||||
Searchable bool `json:"searchable"`
|
||||
|
||||
MFAEnabled bool `json:"mfaEnabled"`
|
||||
|
||||
PushEnabled bool `json:"pushEnabled"`
|
||||
|
||||
Sealable bool `json:"sealable"`
|
||||
|
8
net/web/src/api/addAccountMFA.js
Normal file
8
net/web/src/api/addAccountMFA.js
Normal file
@ -0,0 +1,8 @@
|
||||
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
||||
|
||||
export async function addAccountMFA(token) {
|
||||
const mfa = await fetchWithTimeout(`/account/mfauth?agent=${token}`, { method: 'POST' })
|
||||
checkResponse(mfa);
|
||||
return mfa.json();
|
||||
}
|
||||
|
7
net/web/src/api/removeAccountMFA.js
Normal file
7
net/web/src/api/removeAccountMFA.js
Normal file
@ -0,0 +1,7 @@
|
||||
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
||||
|
||||
export async function removeAccountMFA(token) {
|
||||
let res = await fetchWithTimeout(`/account/mfauth?agent=${token}`, { method: 'DELETE' })
|
||||
checkResponse(res);
|
||||
}
|
||||
|
7
net/web/src/api/setAccountMFA.js
Normal file
7
net/web/src/api/setAccountMFA.js
Normal file
@ -0,0 +1,7 @@
|
||||
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
||||
|
||||
export async function setAccountMFA(token, code) {
|
||||
let res = await fetchWithTimeout(`/account/mfauth?agent=${token}&code=${code}`, { method: 'PUT' })
|
||||
checkResponse(res);
|
||||
}
|
||||
|
@ -3,6 +3,9 @@ import { setAccountSearchable } from 'api/setAccountSearchable';
|
||||
import { setAccountSeal } from 'api/setAccountSeal';
|
||||
import { getAccountStatus } from 'api/getAccountStatus';
|
||||
import { setAccountLogin } from 'api/setAccountLogin';
|
||||
import { addAccountMFA } from 'api/addAccountMFA';
|
||||
import { setAccountMFA } from 'api/setAccountMFA';
|
||||
import { removeAccountMFA } from 'api/removeAccountMFA';
|
||||
import { StoreContext } from './StoreContext';
|
||||
|
||||
export function useAccountContext() {
|
||||
@ -72,6 +75,17 @@ export function useAccountContext() {
|
||||
setSearchable: async (flag) => {
|
||||
await setAccountSearchable(access.current, flag);
|
||||
},
|
||||
enableMFA: async () => {
|
||||
const secret = await addAccountMFA(access.current);
|
||||
console.log("SECRET ", secret);
|
||||
return secret;
|
||||
},
|
||||
disableMFA: async () => {
|
||||
await removeAccountMFA(access.current);
|
||||
},
|
||||
confirmMFA: async (code) => {
|
||||
await setAccountMFA(access.current, code);
|
||||
},
|
||||
setSeal: async (seal, sealKey) => {
|
||||
await setAccountSeal(access.current, seal);
|
||||
await storeContext.actions.setValue("sealKey", sealKey);
|
||||
|
@ -39,6 +39,26 @@ export function AccountAccess() {
|
||||
}
|
||||
};
|
||||
|
||||
const enableMFA = async (enable) => {
|
||||
console.log("ENABLE: ", enable);
|
||||
try {
|
||||
if (enable) {
|
||||
await actions.enableMFA();
|
||||
}
|
||||
else {
|
||||
await actions.disableMFA();
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
console.log(err);
|
||||
modal.error({
|
||||
title: <span style={state.menuStyle}>{state.strings.operationFailed}</span>,
|
||||
content: <span style={state.menuStyle}>{state.strings.tryAgain}</span>,
|
||||
bodyStyle: { borderRadius: 8, padding: 16, ...state.menuStyle },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const saveLogin = async () => {
|
||||
try {
|
||||
await actions.setLogin();
|
||||
@ -84,6 +104,12 @@ export function AccountAccess() {
|
||||
</div>
|
||||
<div className="switchLabel">{state.strings.registry}</div>
|
||||
</div>
|
||||
<div className="switch">
|
||||
<div className="control">
|
||||
<Switch size="small" checked={state.mfaEnabled} onChange={enable => enableMFA(enable)} />
|
||||
</div>
|
||||
<div className="switchLabel">Multi-Factor Authentication</div>
|
||||
</div>
|
||||
<div className="link" onClick={actions.setEditSeal}>
|
||||
<div className="control">
|
||||
<SettingOutlined />
|
||||
@ -238,6 +264,9 @@ export function AccountAccess() {
|
||||
</div>
|
||||
</LoginModal>
|
||||
</Modal>
|
||||
<Modal centerd closable={false} footer={null} visible={state.mfaModal} bodyStyle={{ borderRadius: 8, padding: 16, ...state.menuStyle }} onCancel={actions.dismissMFA}>
|
||||
<div>{ state.mfaSecret }</div>
|
||||
</Modal>
|
||||
</AccountAccessWrapper>
|
||||
);
|
||||
}
|
||||
|
@ -40,6 +40,11 @@ export function useAccountAccess() {
|
||||
videoId: null,
|
||||
videoInputs: [],
|
||||
|
||||
mfaModal: false,
|
||||
mfaEnabled: null,
|
||||
mfaSecret: null,
|
||||
mfaCode: null,
|
||||
|
||||
seal: null,
|
||||
sealKey: null,
|
||||
});
|
||||
@ -60,7 +65,7 @@ export function useAccountAccess() {
|
||||
|
||||
useEffect(() => {
|
||||
const { seal, sealKey, status } = account.state;
|
||||
updateState({ searchable: status?.searchable, seal, sealKey });
|
||||
updateState({ searchable: status?.searchable, mfaEnabled: status?.mfaEnabled, seal, sealKey });
|
||||
}, [account.state]);
|
||||
|
||||
useEffect(() => {
|
||||
@ -307,6 +312,54 @@ export function useAccountAccess() {
|
||||
}
|
||||
}
|
||||
},
|
||||
setCode: async (code) => {
|
||||
updateState({ mfaCode: code });
|
||||
},
|
||||
enableMFA: async () => {
|
||||
if (!state.busy) {
|
||||
try {
|
||||
updateState({ busy: true });
|
||||
const secret = await account.actions.enableMFA();
|
||||
updateState({ busy: false, mfaModal: true, mfaSecret: secret, mfaCode: '' });
|
||||
}
|
||||
catch (err) {
|
||||
console.log(err);
|
||||
updateState({ busy: false });
|
||||
throw new Error('faild to enable mfa');
|
||||
}
|
||||
}
|
||||
},
|
||||
disableMFA: async () => {
|
||||
if (!state.busy) {
|
||||
try {
|
||||
updateState({ busy: true });
|
||||
await account.actions.disableMFA();
|
||||
updateState({ busy: false });
|
||||
}
|
||||
catch (err) {
|
||||
console.log(err);
|
||||
updateState({ busy: false });
|
||||
throw new Error('failed to disable mfa');
|
||||
}
|
||||
}
|
||||
},
|
||||
confirmMFA: async () => {
|
||||
if (!state.busy) {
|
||||
try {
|
||||
updateState({ busy: true });
|
||||
await account.actions.confirmMFA(state.code);
|
||||
updateState({ busy: false });
|
||||
}
|
||||
catch (err) {
|
||||
console.log(err);
|
||||
updateState({ busy: false });
|
||||
throw new Error('failed to confirm mfa');
|
||||
}
|
||||
}
|
||||
},
|
||||
dismissMFA: async () => {
|
||||
updateState({ mfaModal: false });
|
||||
},
|
||||
};
|
||||
|
||||
return { state, actions };
|
||||
|
Loading…
Reference in New Issue
Block a user