change crypto library
This commit is contained in:
parent
b6d186ae0c
commit
c8d6de0556
@ -384,7 +384,7 @@ export const removeAttachmentFile = (id) =>
|
||||
});
|
||||
}
|
||||
|
||||
export const downloadQuestionnaire = ({ filename, download = true }) =>
|
||||
export const downloadQuestionnaire = ({ filename, download = true, base64 = false }) =>
|
||||
{
|
||||
console.log("ACTION", "questionnaireActions", "downloadQuestionnaire()", );
|
||||
|
||||
@ -398,23 +398,29 @@ export const downloadQuestionnaire = ({ filename, download = true }) =>
|
||||
|
||||
console.log("questionnaire", questionnaire);
|
||||
const { main, contacts, signatory_person, founder_persons, head_person, non_profit, } = questionnaire;
|
||||
const playload = { main, contacts, signatory_person, founder_persons, head_person, non_profit, };
|
||||
console.log({ playload });
|
||||
const payload = { main, contacts, signatory_person, founder_persons, head_person, non_profit, };
|
||||
console.log({ payload });
|
||||
|
||||
/* axios.post(`${ process.env.NEXT_PUBLIC_INT_API_HOST }/questionnaire/download`, { questionnaire: playload }, {
|
||||
/* axios.post(`${ process.env.NEXT_PUBLIC_INT_API_HOST }/questionnaire/download`, { questionnaire: payload }, {
|
||||
headers: {
|
||||
"Authorization": `Bearer ${ cookies_list.jwt }`,
|
||||
},
|
||||
})
|
||||
*/
|
||||
|
||||
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/questionnaire/download`, { questionnaire: playload, filename }, {
|
||||
const options = {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/pdf'
|
||||
},
|
||||
responseType: 'arraybuffer',
|
||||
})
|
||||
};
|
||||
|
||||
if(!base64)
|
||||
{
|
||||
options.responseType = "arraybuffer";
|
||||
}
|
||||
|
||||
axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/questionnaire/download`, { questionnaire: payload, filename, base64: download ? false : true }, options)
|
||||
.then((response) =>
|
||||
{
|
||||
if(download)
|
||||
|
||||
222
components/questionnaire/forms/DigitalCertificates.js
Normal file
222
components/questionnaire/forms/DigitalCertificates.js
Normal file
@ -0,0 +1,222 @@
|
||||
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()
|
||||
{
|
||||
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) =>
|
||||
{
|
||||
if(cert.IsValid)
|
||||
{
|
||||
callback(null, [ { id: certificate.id, fields: cert.Subject, valid_to_date: moment(cert.ValidToDate).format("DD.MM.YYYY") } ]);
|
||||
}
|
||||
else
|
||||
{
|
||||
callback(null, []);
|
||||
}
|
||||
});
|
||||
}, (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") }.pdf`;
|
||||
|
||||
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 =>
|
||||
{
|
||||
uploadSignedFile(signature, 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 { 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)
|
||||
{
|
||||
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['INN'] }</span>
|
||||
</p>
|
||||
<p className="item_desc">
|
||||
{ certificate.fields['OGRNIP'] && (<span>ОГРНИП { certificate.fields['OGRNIP'] }</span>) }
|
||||
{ certificate.fields['OGRN'] && (<span>ОГРН { certificate.fields['ОГРН'] }</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="error" 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="error" title="Ошибка" message={ <>Плагин КриптоПРО не активирован, пожалуйста, обновите страницу и подтвердите разрешение для сайта на доступ к списку сертификатов.</> }/>
|
||||
) }
|
||||
{ certificates_error === "ISSUED" && (
|
||||
<FormMessage type="error" title="Ошибка" message={ <>Отсутствуют действующие сертификаты.</> }/>
|
||||
) }
|
||||
{ certificates_error === "MISMATCH" && (
|
||||
<FormMessage type="error" title="Ошибка" message={ <>Подписант не соответствует указанному подписанту в анкете.</> }/>
|
||||
) }
|
||||
</React.Fragment>
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1107,7 +1107,7 @@ class Form_3_Signer extends QuestionnaireForm
|
||||
|
||||
{ errors.indexOf("signatory_person.identical") > -1 &&
|
||||
(
|
||||
<FormMessage type="error" title="Ошибка" message="Единоличный исполнительный орган и подписант договора лизинга совпадают. Укажите иного подписанта или откажитесь от указания иного подписанта."/>
|
||||
<FormMessage type="error" title="Ошибка" message={ `Выбранный подписант совпадает с единоличным исполнительным органом. Выберите иного подписанта или снимите галку "Подписант отличается от единоличного исполнительного органа".` }/>
|
||||
) }
|
||||
|
||||
<div className="form_field">
|
||||
|
||||
@ -9,12 +9,14 @@ import { SpinnerCircular } from "spinners-react";
|
||||
import { connect } from "react-redux";
|
||||
import { withRouter } from 'next/router';
|
||||
import moment from "moment";
|
||||
import NoSSR from "@mpth/react-no-ssr";
|
||||
|
||||
import QuestionnaireForm from "../QuestionnaireForm";
|
||||
import { MatchMedia } from '../../../../utils/mediaqueries';
|
||||
import { reduxWrapper } from '../../../../store';
|
||||
import DigitalSignaturesList from "../DigitalSignaturesList";
|
||||
import { downloadQuestionnaire } from "../../../../actions";
|
||||
import DigitalCertificates from "../DigitalCertificates";
|
||||
import FormMessage from "../FormMessage";
|
||||
|
||||
class Form_8_Signing extends QuestionnaireForm
|
||||
@ -159,8 +161,12 @@ class Form_8_Signing extends QuestionnaireForm
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<DigitalSignaturesList form={ null } main={ main } company={ company } onSignDigital={ this._handle_onSignDigital }/>
|
||||
<NoSSR>
|
||||
<DigitalCertificates main={ main } company={ company } onSignDigital={ this._handle_onSignDigital }/>
|
||||
</NoSSR>
|
||||
|
||||
) }
|
||||
{/*<DigitalSignaturesList form={ null } main={ main } company={ company } onSignDigital={ this._handle_onSignDigital }/>*/}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
|
||||
@ -53,6 +53,7 @@
|
||||
"react-widgets": "^5.5.1",
|
||||
"redux": "^4.1.2",
|
||||
"redux-persist": "^6.0.0",
|
||||
"ruscryptojs": "^2.6.1",
|
||||
"spinners-react": "^1.0.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@ -120,7 +120,7 @@ export default async function handler(req, res)
|
||||
console.log("API", "questionnaire", "get");
|
||||
console.log(req.body);
|
||||
console.log("-".repeat(50));
|
||||
const { questionnaire, filename } = req.body;
|
||||
const { questionnaire, filename, base64 } = req.body;
|
||||
|
||||
await cors(req, res);
|
||||
|
||||
@ -326,10 +326,17 @@ export default async function handler(req, res)
|
||||
//res.setHeader('Content-Type', 'application/pdf');
|
||||
//res.send(pdfBytes);
|
||||
console.log("pdfBytes.size", pdfBytes, pdfBytes.byteLength);
|
||||
if(base64)
|
||||
{
|
||||
//, 'binary'
|
||||
res.status(200).send(Buffer.from(pdfBytes).toString('base64'));
|
||||
}
|
||||
else
|
||||
{
|
||||
res.setHeader("filename", filename);
|
||||
res.setHeader('Content-Type', 'application/pdf');
|
||||
res.send(Buffer.from(pdfBytes));
|
||||
|
||||
res.status(200).send(Buffer.from(pdfBytes));
|
||||
}
|
||||
//res.setHeader('Content-Type', 'application/pdf');
|
||||
//res.status(200).send(pdfBytes);
|
||||
}
|
||||
|
||||
24
yarn.lock
24
yarn.lock
@ -2071,6 +2071,11 @@ console-browserify@^1.1.0:
|
||||
resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336"
|
||||
integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==
|
||||
|
||||
console-polyfill@^0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/console-polyfill/-/console-polyfill-0.3.0.tgz#84900902a18c47a5eba932be75fa44d23e8af861"
|
||||
integrity sha512-w+JSDZS7XML43Xnwo2x5O5vxB0ID7T5BdqDtyqT6uiCAX2kZAgcWxNaGqT97tZfSHzfOcvrfsDAodKcJ3UvnXQ==
|
||||
|
||||
constants-browserify@1.0.0, constants-browserify@^1.0.0, constants-browserify@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
|
||||
@ -4054,6 +4059,11 @@ js-file-download@^0.4.12:
|
||||
resolved "https://registry.yarnpkg.com/js-file-download/-/js-file-download-0.4.12.tgz#10c70ef362559a5b23cdbdc3bd6f399c3d91d821"
|
||||
integrity sha512-rML+NkoD08p5Dllpjo0ffy4jRHeY6Zsapvr/W86N7E0yuzAO6qa5X9+xog6zQNlH102J7IXljNY2FtS6Lj3ucg==
|
||||
|
||||
js-sha1@^0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/js-sha1/-/js-sha1-0.6.0.tgz#adbee10f0e8e18aa07cdea807cf08e9183dbc7f9"
|
||||
integrity sha512-01gwBFreYydzmU9BmZxpVk6svJJHrVxEN3IOiGl6VO93bVKYETJ0sIth6DASI6mIFdt7NmfX9UiByRzsYHGU9w==
|
||||
|
||||
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||
@ -5954,6 +5964,20 @@ run-parallel@^1.1.9:
|
||||
dependencies:
|
||||
queue-microtask "^1.2.2"
|
||||
|
||||
ruscryptojs@^2.6.1:
|
||||
version "2.6.1"
|
||||
resolved "https://registry.yarnpkg.com/ruscryptojs/-/ruscryptojs-2.6.1.tgz#f9af6a95d63d8f575f1c65ea510ec586c2ab753b"
|
||||
integrity sha512-CV41M1w02O5Yb9KLUBtDfIgPvgp+OjFxe7nT6uJ8lYyJInNIZeYBsUaegRVto01pNCG353DBlF9DWckJZ6/4Iw==
|
||||
dependencies:
|
||||
console-polyfill "^0.3.0"
|
||||
js-sha1 "^0.6.0"
|
||||
rutoken "^1.0.8"
|
||||
|
||||
rutoken@^1.0.8:
|
||||
version "1.0.8"
|
||||
resolved "https://registry.yarnpkg.com/rutoken/-/rutoken-1.0.8.tgz#443e16022fa8e1d7c638ba852f91d7fcb3a68be7"
|
||||
integrity sha512-85C4CJk650iZauCmOes2TeQmVjkWviI1ys3E7nDw8pWlMI2mBuLz1fCD30ZjAfnNQ6OL19OMTYDNPFrJ60NfEA==
|
||||
|
||||
safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user