This repository has been archived by the owner on Jun 3, 2020. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
settings: Add an option to validate and add custom/self-signed certif…
…icates. This PR helps to validate custom/self-signed certificates for servers by saving the certificate file in certificates folder in user's appData folder. We now use this certificate with the request while validating the server when adding the organization. This validation of certificate is done by the request module itself. Fixes: #126.
- Loading branch information
1 parent
99a1711
commit 0a893c9
Showing
7 changed files
with
249 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
'use-strict'; | ||
|
||
const { dialog } = require('electron').remote; | ||
|
||
const BaseComponent = require(__dirname + '/../../components/base.js'); | ||
const CertificateUtil = require(__dirname + '/../../utils/certificate-util.js'); | ||
const DomainUtil = require(__dirname + '/../../utils/domain-util.js'); | ||
|
||
class AddCertificate extends BaseComponent { | ||
constructor(props) { | ||
super(); | ||
this.props = props; | ||
this._certFile = ''; | ||
} | ||
|
||
template() { | ||
return ` | ||
<div class="settings-card server-center certificates-card"> | ||
<div class="certificate-input"> | ||
<div>Organization URL :</div> | ||
<input class="setting-input-value" autofocus placeholder="your-organization.zulipchat.com or zulip.your-organization.com"/> | ||
</div> | ||
<div class="certificate-input"> | ||
<div>Custom CA's certificate file :</div> | ||
<button id="add-certificate-button">Add</button> | ||
</div> | ||
</div> | ||
`; | ||
} | ||
|
||
init() { | ||
this.$addCertificate = this.generateNodeFromTemplate(this.template()); | ||
this.props.$root.appendChild(this.$addCertificate); | ||
this.addCertificateButton = this.$addCertificate.querySelector('#add-certificate-button'); | ||
this.serverUrl = this.$addCertificate.querySelectorAll('input.setting-input-value')[0]; | ||
this.initListeners(); | ||
} | ||
|
||
validateAndAdd() { | ||
const certificate = this._certFile; | ||
const serverUrl = this.serverUrl.value; | ||
if (certificate !== '' && serverUrl !== '') { | ||
const server = encodeURIComponent(DomainUtil.formatUrl(serverUrl)); | ||
const fileName = certificate.substring(certificate.lastIndexOf('/') + 1); | ||
const copy = CertificateUtil.copyCertificate(server, certificate, fileName); | ||
if (!copy) { | ||
console.log('We encountered error while saving the certificate.'); | ||
return; | ||
} | ||
CertificateUtil.setCertificate(server, fileName); | ||
dialog.showMessageBox({ | ||
title: 'Success', | ||
message: `Certificate saved!` | ||
}); | ||
this.serverUrl.value = ''; | ||
} else { | ||
dialog.showErrorBox('Error', `Please, ${serverUrl === '' ? | ||
'Enter an Organization URL' : 'Choose certificate file'}`); | ||
} | ||
} | ||
|
||
addHandler() { | ||
const showDialogOptions = { | ||
title: 'Select file', | ||
defaultId: 1, | ||
properties: ['openFile'], | ||
filters: [{ name: 'crt, pem', extensions: ['crt', 'pem'] }] | ||
}; | ||
dialog.showOpenDialog(showDialogOptions, selectedFile => { | ||
if (selectedFile) { | ||
this._certFile = selectedFile[0] || ''; | ||
this.validateAndAdd(); | ||
} | ||
}); | ||
} | ||
|
||
initListeners() { | ||
this.addCertificateButton.addEventListener('click', () => { | ||
this.addHandler(); | ||
}); | ||
|
||
this.serverUrl.addEventListener('keypress', event => { | ||
const EnterkeyCode = event.keyCode; | ||
|
||
if (EnterkeyCode === 13) { | ||
this.addHandler(); | ||
} | ||
}); | ||
} | ||
} | ||
|
||
module.exports = AddCertificate; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
'use strict'; | ||
|
||
const { app, dialog } = require('electron').remote; | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const JsonDB = require('node-json-db'); | ||
const Logger = require('./logger-util'); | ||
const { initSetUp } = require('./default-util'); | ||
|
||
initSetUp(); | ||
|
||
const logger = new Logger({ | ||
file: `certificate-util.log`, | ||
timestamp: true | ||
}); | ||
|
||
let instance = null; | ||
const certificatesDir = `${app.getPath('userData')}/certificates`; | ||
|
||
class CertificateUtil { | ||
constructor() { | ||
if (instance) { | ||
return instance; | ||
} else { | ||
instance = this; | ||
} | ||
|
||
this.reloadDB(); | ||
return instance; | ||
} | ||
getCertificate(server, defaultValue = null) { | ||
this.reloadDB(); | ||
const value = this.db.getData('/')[server]; | ||
if (value === undefined) { | ||
return defaultValue; | ||
} else { | ||
return value; | ||
} | ||
} | ||
// Function to copy the certificate to userData folder | ||
copyCertificate(server, location, fileName) { | ||
let copied = false; | ||
const filePath = `${certificatesDir}/${fileName}`; | ||
try { | ||
fs.copyFileSync(location, filePath); | ||
copied = true; | ||
} catch (err) { | ||
dialog.showErrorBox( | ||
'Error saving certificate', | ||
'We encountered error while saving the certificate.' | ||
); | ||
logger.error('Error while copying the certificate to certificates folder.'); | ||
logger.error(err); | ||
console.log(err); | ||
} | ||
return copied; | ||
} | ||
setCertificate(server, fileName) { | ||
const filePath = `${certificatesDir}/${fileName}`; | ||
this.db.push(`/${server}`, filePath, true); | ||
this.reloadDB(); | ||
} | ||
removeCertificate(server) { | ||
this.db.delete(`/${server}`); | ||
this.reloadDB(); | ||
} | ||
reloadDB() { | ||
const settingsJsonPath = path.join(app.getPath('userData'), '/certificates.json'); | ||
try { | ||
const file = fs.readFileSync(settingsJsonPath, 'utf8'); | ||
JSON.parse(file); | ||
} catch (err) { | ||
if (fs.existsSync(settingsJsonPath)) { | ||
fs.unlinkSync(settingsJsonPath); | ||
dialog.showErrorBox( | ||
'Error saving settings', | ||
'We encountered error while saving the certificate.' | ||
); | ||
logger.error('Error while JSON parsing certificates.json: '); | ||
logger.error(err); | ||
} | ||
} | ||
this.db = new JsonDB(settingsJsonPath, true, true); | ||
} | ||
} | ||
|
||
module.exports = new CertificateUtil(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters