/home/edulekha/www/wp-content/plugins/really-simple-ssl/settings/src/LetsEncrypt/LetsEncrypt.js
import {useState, useEffect, useRef} from "@wordpress/element";
import * as rsssl_api from "../utils/api";
import sleeper from "../utils/sleeper";
import Directories from "./Directories";
import DnsVerification from "./DnsVerification";
import Generation from "./Generation";
import Activate from "./Activate";
import Installation from "./Installation";
import { __ } from '@wordpress/i18n';
import {useUpdateEffect} from 'react-use';
import Icon from "../utils/Icon";
const LetsEncrypt = (props) => {
const [id, setId] = useState(props.field.id);
const [actionUpdated, setActionUpdated] = useState(false);
const [progress, setProgress] = useState(0);
const actionIndex = useRef(0);
const sleep = useRef(1500);
const maxAttempts = useRef(1);
const intervalId = useRef(false);
const lastActionStatus = useRef('');
// const previousProgress = useRef(0);
const previousActionIndex = useRef(-1);
useEffect(() => {
props.handleNextButtonDisabled(true);
runTest(0);
intervalId.current = setInterval(() => setProgress((progress) => progress + 0.2), 100);
}, [])
const restartTests = () => {
//clear statuses to ensure the bullets are grey
let actions = props.field.actions;
for ( const action of actions ) {
action.status='inactive';
}
props.field.actions = actions;
actionIndex.current = 0;
previousActionIndex.current =-1;
lastActionStatus.current = '';
setProgress(0);
runTest(0);
}
const getAction = () => {
let newActions = props.field.actions;
return newActions[actionIndex.current];
}
useUpdateEffect(()=> {
let maxIndex = props.field.actions.length-1;
if (actionIndex.current>previousActionIndex.current) {
previousActionIndex.current = actionIndex.current;
setProgress( ( 100 / maxIndex ) * actionIndex.current);
}
//ensure that progress does not get to 100 when retries are still running
let currentAction = getAction();
if ( currentAction && currentAction.do==='retry' && currentAction.attemptCount>1 ){
setProgress(90);
}
if ( props.refreshTests ){
props.resetRefreshTests();
restartTests();
}
})
const adjustActionsForDNS = (actions) => {
//find verification_type
let verification_type = props.getFieldValue('verification_type');
if ( !verification_type ) verification_type = 'dir';
if ( verification_type==='dns' ) {
//check if dns verification already is added
let dnsVerificationAdded = false;
actions.forEach(function(action, i) {
if (action.action==="verify_dns"){
dnsVerificationAdded = true;
}
});
//find bundle index
let create_bundle_index = -1;
actions.forEach(function(action, i) {
if (action.action==="create_bundle_or_renew"){
create_bundle_index = i;
}
});
if (!dnsVerificationAdded && create_bundle_index>0) {
//store create bundle action
let createBundleAction = actions[create_bundle_index];
//overwrite create bundle action
let newAction = {};
newAction.action = 'verify_dns';
newAction.description = __("Verifying DNS records...", "really-simple-ssl");
newAction.attempts = 2;
actions[create_bundle_index] = newAction;
actions.push(createBundleAction);
}
}
return actions;
}
const processTestResult = (action) => {
lastActionStatus.current = action.status;
let maxIndex = props.field.actions.length-1;
if (action.status==='success') {
action.attemptCount = 0;
} else {
if (!Number.isInteger(action.attemptCount)) {
action.attemptCount = 0;
}
action.attemptCount +=1;
}
setActionUpdated(true);
//used for dns verification actions
var event = new CustomEvent('rsssl_le_response', { detail: action });
document.dispatchEvent(event);
//if all tests are finished with success
//finalize happens when halfway through our tests it's finished. We can skip all others.
if ( action.do === 'finalize' ) {
clearInterval(intervalId.current);
props.field.actions.forEach(function(action,i){
if (i>actionIndex.current) {
action.hide=true;
}
});
actionIndex.current = maxIndex;
props.handleNextButtonDisabled(false);
} else if (action.do === 'continue' || action.do === 'skip' ) {
//new action, so reset the attempts count
action.attemptCount=1;
//skip: drop previous completely, skip to next.
if ( action.do === 'skip' ) {
action.hide = true;
}
//move to next action, but not if we're already on the max
if ( maxIndex > actionIndex.current ) {
actionIndex.current = actionIndex.current+1;
runTest(actionIndex.current);
} else {
actionIndex.current = maxIndex;
props.handleNextButtonDisabled(false);
clearInterval(intervalId.current);
}
} else if (action.do === 'retry' ) {
if ( action.attemptCount >= maxAttempts.current ) {
actionIndex.current = maxIndex;
clearInterval(intervalId.current);
} else {
// clearInterval(intervalId.current);
runTest(actionIndex.current);
}
} else if ( action.do === 'stop' ){
clearInterval(intervalId.current);
}
}
const runTest = () => {
setActionUpdated(false);
if ( props.field.id==='generation' ) {
props.field.actions = adjustActionsForDNS(props.field.actions);
}
let action = getAction();
let test = action.action;
const startTime = new Date();
maxAttempts.current = action.attempts;
rsssl_api.runLetsEncryptTest(test, props.field.id ).then( ( response ) => {
const endTime = new Date();
let timeDiff = endTime - startTime; //in ms
const elapsedTime = Math.round(timeDiff);
let action = getAction();
action.status = response.status ? response.status : 'inactive';
action.hide = false;
action.description = response.message;
action.do = response.action;
action.output = response.output ? response.output : false;
sleep.current = 500;
if (elapsedTime<1500) {
sleep.current = 1500-elapsedTime;
}
}).then(sleeper(sleep.current)).then(() => {
processTestResult(action);
});
}
const getStyles = () => {
return Object.assign(
{},
{width: progress+"%"},
);
}
const getStatusIcon = (action) => {
if (!statuses.hasOwnProperty(action.status)) {
return statuses['inactive'].icon;
}
return statuses[action.status].icon
}
const getStatusColor = (action) => {
if (!statuses.hasOwnProperty(action.status)) {
return statuses['inactive'].color;
}
return statuses[action.status].color;
}
let progressBarColor = lastActionStatus.current ==='error' ? 'rsssl-orange' : '';
if ( !props.field.actions ) {
return (<></>);
}
// keep current action, before it is filtered. The actionindex doesn't match anymore after filtering
let currentAction = props.field.actions[actionIndex.current];
//filter out skipped actions
let actions = props.field.actions.filter(action => action.hide !== true);
const statuses = {
'inactive': {
'icon': 'circle-times',
'color': 'grey',
},
'warning': {
'icon': 'circle-times',
'color': 'orange',
},
'error': {
'icon': 'circle-times',
'color': 'red',
},
'success': {
'icon': 'circle-check',
'color': 'green',
},
};
return (
<>
<div className="rsssl-lets-encrypt-tests">
<div className="rsssl-progress-bar"><div className="rsssl-progress"><div className={'rsssl-bar ' + progressBarColor} style={getStyles()}></div></div></div>
<div className="rsssl_letsencrypt_container rsssl-progress-container field-group">
<ul>
{actions.map((action, i) =>
<li key={i}>
<Icon name = {getStatusIcon(action)} color = {getStatusColor(action)} />
{action.do==='retry' && action.attemptCount >=1 && <>{__("Attempt %s.", "really-simple-ssl").replace('%s', action.attemptCount)} </>}
<span dangerouslySetInnerHTML={{__html:action.description}}></span>
</li>
)
}
</ul>
</div>
{props.field.id === 'directories' && <Directories save={props.save} selectMenu={props.selectMenu} field={props.field} updateField={props.updateField} addHelp={props.addHelp} progress={progress} action={currentAction}/> }
{props.field.id === 'dns-verification' && <DnsVerification save={props.save} selectMenu={props.selectMenu} field={props.field} updateField={props.updateField} addHelp={props.addHelp} progress={progress} action={currentAction}/> }
{props.field.id === 'generation' && <Generation restartTests={restartTests} save={props.save} selectMenu={props.selectMenu} field={props.field} updateField={props.updateField} addHelp={props.addHelp} progress={progress} action={currentAction}/> }
{props.field.id === 'installation' && <Installation restartTests={restartTests} save={props.save} selectMenu={props.selectMenu} field={props.field} updateField={props.updateField} addHelp={props.addHelp} progress={progress} action={currentAction}/> }
{props.field.id === 'activate' && <Activate restartTests={restartTests} save={props.save} selectMainMenu={props.selectMainMenu} selectMenu={props.selectMenu} field={props.field} updateField={props.updateField} addHelp={props.addHelp} progress={progress} action={currentAction}/> }
</div>
</>
)
}
export default LetsEncrypt;