/*
* User certificates
* @author xmax
*/
const UB = require('@unitybase/ub')
const App = UB.App
const Session = UB.Session
/* global uba_usercertificate */
// eslint-disable-next-line camelcase
const me = uba_usercertificate
me.on('insert:before', setCertBlobAndAttrs)
me.on('update:before', setCertBlobAndAttrs)
me.on('delete.before', logoutUserBeforeCertDelete)
me.on('insert:after', clearBlob)
me.on('update:after', clearBlobAndLogoutAUser)
me.entity.addMethod('getCertificate')
/**
* @private
* @param {ubMethodParams} ctx
*/
function setCertBlobAndAttrs (ctx) {
const execParams = ctx.mParams.execParams
Object.keys(execParams)
if (execParams.certificate) {
me.parseCertificateAndSetAttrs(execParams)
}
}
/**
* @public
* @param execParams
*/
me.parseCertificateAndSetAttrs = function (execParams) {
const iitCrypto = require('@ub-d/iit-crypto')
const certBin = Buffer.from(execParams.certificate, 'base64')
const certJson = iitCrypto.parseCertificate(certBin)
execParams.setBLOBValue('certificate', certBin)
execParams.certParsed = JSON.stringify(certJson)
execParams.serial = certJson.Serial
execParams.issuer_serial = certJson.IssuerPublicKeyID
execParams.issuer_cn = certJson.IssuerCN
execParams.isForSigning = certJson.KeyUsage && (certJson.KeyUsage.indexOf('ЕЦП') !== -1)
}
/**
* @private
* @param {ubMethodParams} ctxt
*/
function logoutUserBeforeCertDelete (ctxt) {
const rowID = ctxt.mParams.execParams.ID
const userID = UB.Repository(me.entity.name).attrs('userID').where('ID', '=', rowID).selectScalar()
App.removeUserSessions(userID)
}
/**
* @private
* @param {ubMethodParams} ctxt
*/
function clearBlobAndLogoutAUser (ctxt) {
const execParams = ctxt.mParams.execParams
if (execParams.certificate) {
execParams.certificate = ''
}
let userID = execParams.userID
if (!userID) {
userID = UB.Repository(me.entity.name).attrs('userID').where('ID', '=', execParams.ID).selectScalar()
}
App.removeUserSessions(userID)
}
/**
* @private
* @param {ubMethodParams} ctxt
*/
function clearBlob (ctxt) {
const execParams = ctxt.mParams.execParams
if (execParams.certificate) {
execParams.certificate = ''
}
}
/**
* Get user *SIGNING* certificate
* @method getCurrentUserCertificate
* @public
* @param {number} [userID]
* @param {boolean} [forSigning=true]
* @return {ArrayBuffer|null} certificate binary or null if actual certificate is not found
*/
function getCurrentUserCertificate (userID, forSigning = true) {
const store = UB.Repository('uba_usercertificate')
.attrs(['certificate'])
.where('userID', '=', userID || Session.userID)
.whereIf(forSigning, 'isForSigning', '=', true)
.where('disabled', '=', false)
.where('revoked', '=', false)
.selectAsStore()
if (store.eof) return null
return store.getAsBuffer('certificate')
}
/**
* Retrieve certificate as:
* - base64 encoded string, if called as ubql
* - binary, if called as REST `/rest/uba_usercertificate/getCertificate?ID=223`
* - if called w/o ID, current user *SIGNING* certificate is returned
*
* @param {ubMethodParams} [ctxt]
* @param {number} [ctxt.mParams.ID]
* @param {THTTPRequest} [req]
* @param {THTTPResponse} [resp]
* @method getCertificate
* @memberOf uba_usercertificate_ns.prototype
* @memberOfModule @unitybase/uba
* @published
*/
me.getCertificate = function (ctxt, req, resp) {
let certID
if (req) { // endpoint is called as rest/uba_usercertificate/getCertificate?ID=1231
certID = req.parsedParameters.ID
} else {
certID = ctxt.mParams.ID
}
let certificate
if (certID) {
const store = UB.Repository('uba_usercertificate')
.attrs(['ID', 'certificate'])
.where('ID', '=', certID)
.select()
if (store.eof) throw new Error('not found')
certificate = store.getAsBuffer('certificate')
} else {
certificate = getCurrentUserCertificate()
if (!certificate) throw new Error('not found')
}
if (req) {
resp.writeEnd(certificate)
resp.writeHead('Content-Type: application/x-x509-user-cert')
resp.statusCode = 200
} else {
certificate = Buffer.from(certificate)
certificate = certificate.toString('base64')
ctxt.dataStore.initialize({ fieldCount: 1, values: ['certificate', certificate], rowCount: 1 })
}
}
me.getCurrentUserCertificate = getCurrentUserCertificate