2023-11-22 21:35:33 +03:00

289 lines
9.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React from "react";
import Link from "next/link";
import { SpinnerCircular } from "spinners-react";
import moment from "moment";
import dynamic from 'next/dynamic';
import { concatSeries } from 'async';
import fileDownload from 'js-file-download';
import FormMessage from "./FormMessage";
import { downloadQuestionnaire, uploadSignedFile } from "../../../actions";
//import { generateSignature } from "../../../utils/digital_signature";
export default class DigitalCertificates extends React.Component
{
constructor(props)
{
super(props);
this.state = {
loading: true,
certificates: [],
certificates_error: null,
certificate_selected: undefined,
signing: false,
};
this.cryptopro = null;
}
async componentDidMount()
{
const { company, main, head_person } = this.props;
//console.log({ company, main });
//console.log("DC", "CDM");
const { CryptoPro } = await import('ruscryptojs');
this.cryptopro = new CryptoPro();
this.cryptopro.init()
.then((info) =>
{
//console.log('Initialized', info);
this.cryptopro.listCertificates()
.then((certificates_list) =>
{
//console.log({ certificates_list });
concatSeries(certificates_list, (certificate, callback) =>
{
//console.log(certificate.id, certificate.name);
this.cryptopro.certificateInfo(certificate.id)
.then((cert) =>
{
//console.log({ cert });
if(cert.IsValid)
{
if(cert.Subject['OGRNIP'] !== undefined && cert.Subject['OGRNIP'] !== null && cert.Subject['OGRNIP'] !== "")
{
if(cert.Subject['INN'] !== undefined && cert.Subject['INN'] !== null && cert.Subject['INN'] !== "")
{
if(company.inn === cert.Subject['INN'])
{
callback(null, [ { id: certificate.id, fields: cert.Subject, valid_to_date: moment(cert.ValidToDate).format("DD.MM.YYYY") } ]);
}
else
{
callback(null, []);
}
}
else
{
callback(null, []);
}
}
else
{
if(cert.Subject['INNLE'] !== undefined && cert.Subject['INNLE'] !== null && cert.Subject['INNLE'] !== "")
{
let owner_valid = true;
const fields = [ "lastname", "firstname", "middlename", ];
const cert_owner = `${ cert.Subject['SN']} ${ cert.Subject['G']}`.toUpperCase();
for(let i in fields)
{
if(head_person[fields[i]] !== null && head_person[fields[i]] !== "")
{
if(cert_owner.indexOf(head_person[fields[i]].toUpperCase().trim()) < 0)
{
owner_valid = false;
}
}
}
if(owner_valid)
{
callback(null, [ { id: certificate.id, fields: cert.Subject, valid_to_date: moment(cert.ValidToDate).format("DD.MM.YYYY") } ]);
}
else
{
callback(null, []);
}
}
else
{
callback(null, []);
}
}
}
else
{
callback(null, []);
}
})
.catch((error_certificates_info) =>
{
console.error({ error_certificates_info });
this.setState({ loading: false, certificates_error: "CERTIFICATES" });
});
}, (error, certificates) =>
{
if(certificates.length === 0)
{
this.setState({ loading: false, certificates_error: "ISSUED" });
}
else
{
this.setState({ loading: false, certificates });
}
});
})
.catch((error_certificates_list) =>
{
console.error({ error_certificates_list });
this.setState({ loading: false, certificates_error: "CERTIFICATES" });
});
})
.catch((error_init) =>
{
console.error({ error_init });
this.setState({ loading: false, certificates_error: "NOT_INSTALLED" });
});
}
_sign = () =>
{
this.setState({ signing: true }, () =>
{
const { company, main, onSignDigital } = this.props;
const filename = `${ main.inn }_questionnaire_${ moment().format("DDMMYYYY_HHmmss") }.sig`;
downloadQuestionnaire({ filename, download: false, base64: true })
.then(({ file }) =>
{
let file_to_sign = file;
const now = moment().format("DDMMYYYY_HHmmss");
this.cryptopro.signData(file_to_sign, this.state.certificate_selected.id)
.then(signature =>
{
//console.log({ signature });
let signature_file = new File([ signature ], filename);
uploadSignedFile(signature_file, company.questionnaire_id, true)
.then(() =>
{
onSignDigital();
})
.catch(() =>
{
this.setState({ signing: false });
});
})
.catch((error_sign) =>
{
console.error({ error_sign });
this.setState({ signing: false });
})
})
.catch((e) =>
{
console.error("exception on sign");
console.error(e);
});
});
}
render()
{
const { company, main, head_person } = this.props;
const { loading, certificates, certificates_error, certificate_selected, signing } = this.state;
//console.log("render()", { certificates });
if(loading)
{
return (
<div style={{ minHeight: 200, display: "flex", justifyContent: "center", alignItems: "center", }}>
<SpinnerCircular size={ 90 } thickness={ 51 } speed={ 100 } color="rgba(28, 1, 169, 1)" secondaryColor="rgba(236, 239, 244, 1)" />
</div>
);
}
else
{
if(certificates_error === null)
{
console.log({ certificates });
return (
<React.Fragment>
<div className="feed">
<p>Выберите подписанта</p>
<div className="feed_list">
{ certificates.map((certificate, index) => (
<div className="form_field checkbox" key={ index }>
<input type="radio"
hidden=""
id={ `certificate_${ certificate.id }` }
name={ `certificate_${ certificate.id }` }
checked={ certificate_selected !== undefined && certificate_selected.id === certificate.id ? true : false }
onChange={ () => { this.setState({ certificate_selected: certificate }) } }
/>
<label htmlFor={ `certificate_${ certificate.id }` }>
<div className="feed_item user">
<img src="/assets/images/icons/avatar.svg" alt="" />
<div>
<p className="item_title">{ certificate.fields['CN'].replace(/"/g, '') }</p>
<p className="item_desc">
{ certificate.fields['SN'] ? (<span>{ certificate.fields['SN'] } { certificate.fields['G'] }</span>) : null }
</p>
<p className="item_desc">
<span>ИНН { certificate.fields['INNLE'] !== undefined && certificate.fields['INNLE'] !== null ? certificate.fields['INNLE'] : certificate.fields['INN'] }</span>
</p>
<p className="item_desc">
{ certificate.fields['OGRNIP'] && (<span>ОГРНИП { certificate.fields['OGRNIP'] }</span>) }
{ certificate.fields['OGRN'] && (<span>ОГРН { certificate.fields['OGRN'] }</span>) }
</p>
<p className="item_desc">
<span>Подпись действительна до { certificate.valid_to_date }</span>
</p>
</div>
</div>
</label>
</div>
)) }
</div>
</div>
<div className="action" style={{marginBottom: "20px"}}>
<div></div>
<button
type="submit"
className="button button-blue"
disabled={ certificate_selected !== undefined ? false : true }
onClick={ this._sign }
style={{ minWidth: "250px" }}
>
{ signing ? (
<SpinnerCircular size={24} thickness={100} speed={100} color="rgba(255, 255, 255, 1)" secondaryColor="rgba(255, 255, 255, 0.5)" style={{ marginTop: "4px" }}/>
) : "Подписать выбранной подписью" }
</button>
</div>
</React.Fragment>
)
}
else
{
return (
<React.Fragment>
{ certificates_error === "NOT_INSTALLED" && (
<FormMessage type="moderate" title="Внимание" message={ <>Плагин КриптоПРО не установлен, <Link href="https://cryptopro.ru/products/cades/plugin"><a target="_blank" rel="noopener noreferrer" style={{ color: "white", textDecoration: "underline" }}>посмотрите инструкцию</a></Link> как установить плагин КриптоПРО.</> }/>
) }
{ certificates_error === "CERTIFICATES" && (
<FormMessage type="moderate" title="Ошибка" message={ <>Плагин КриптоПРО не активирован, пожалуйста, обновите страницу и подтвердите разрешение для сайта на доступ к списку сертификатов.</> }/>
) }
{ certificates_error === "ISSUED" && (
<FormMessage type="moderate" title="Ошибка" message={ <>Анкету необходимо подписать по ЭЦП сертификатом юридического лица с ИНН: { company.inn }, выданного: { head_person.lastname } { head_person.firstname } { head_person.middlename }. Такой сертификат не найден.</> }/>
) }
{ certificates_error === "MISMATCH" && (
<FormMessage type="moderate" title="Ошибка" message={ <>Подписант не соответствует указанному подписанту в анкете.</> }/>
) }
</React.Fragment>
)
}
}
}
}