mirror of
https://github.com/espocrm/espocrm.git
synced 2026-06-28 06:56:05 +00:00
app secrets
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2024 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Classes\Record\AppSecret;
|
||||
|
||||
use Espo\Core\Exceptions\BadRequest;
|
||||
use Espo\Core\Record\Input\Data;
|
||||
use Espo\Core\Record\Input\Filter;
|
||||
use Espo\Core\Utils\Crypt;
|
||||
|
||||
/**
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
class ValueInputFilter implements Filter
|
||||
{
|
||||
private const ATTR_VALUE = 'value';
|
||||
|
||||
public function __construct(private Crypt $crypt) {}
|
||||
|
||||
/**
|
||||
* @throws BadRequest
|
||||
*/
|
||||
public function filter(Data $data): void
|
||||
{
|
||||
$value = $data->get(self::ATTR_VALUE);
|
||||
|
||||
if ($value !== null) {
|
||||
if (!is_string($value)) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
$data->set(self::ATTR_VALUE, $this->crypt->encrypt($value));
|
||||
}
|
||||
}
|
||||
}
|
||||
43
application/Espo/Controllers/AppSecret.php
Normal file
43
application/Espo/Controllers/AppSecret.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2024 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use Espo\Core\Controllers\Record;
|
||||
|
||||
/**
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
class AppSecret extends Record
|
||||
{
|
||||
protected function checkAccess(): bool
|
||||
{
|
||||
return $this->user->isAdmin();
|
||||
}
|
||||
}
|
||||
65
application/Espo/Entities/AppSecret.php
Normal file
65
application/Espo/Entities/AppSecret.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2024 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Entities;
|
||||
|
||||
use Espo\Core\ORM\Entity;
|
||||
|
||||
class AppSecret extends Entity
|
||||
{
|
||||
public const ENTITY_TYPE = 'AppSecret';
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->get('name');
|
||||
}
|
||||
|
||||
public function getValue(): string
|
||||
{
|
||||
return (string) $this->get('value');
|
||||
}
|
||||
|
||||
public function setName(string $name): self
|
||||
{
|
||||
$this->set('name', $name);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Do not use.
|
||||
* @todo Rename to setValue in v9.0.
|
||||
*/
|
||||
public function setSecretValue(string $value): self
|
||||
{
|
||||
$this->set('value', $value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,7 @@
|
||||
"Auth Tokens": "Auth Tokens",
|
||||
"Auth Log": "Auth Log",
|
||||
"App Log": "App Log",
|
||||
"App Secrets": "App Secrets",
|
||||
"Authentication": "Authentication",
|
||||
"Currency": "Currency",
|
||||
"Integrations": "Integrations",
|
||||
@@ -297,6 +298,7 @@
|
||||
"templateManager": "Customize message templates.",
|
||||
"authLog": "Login history.",
|
||||
"appLog": "Application log.",
|
||||
"appSecrets": "Store sensitive information like API keys, passwords, and other secrets.",
|
||||
"leadCapture": "API entry points for Web-to-Lead.",
|
||||
"attachments": "All file attachments stored in the system.",
|
||||
"systemRequirements": "System Requirements for EspoCRM.",
|
||||
@@ -325,7 +327,8 @@
|
||||
"entityManager": "fields,relations,relationships",
|
||||
"templateManager": "notifications",
|
||||
"jobs": "cron",
|
||||
"labelManager": "language,translation"
|
||||
"labelManager": "language,translation",
|
||||
"appSecrets": "key,keys,password"
|
||||
},
|
||||
"options": {
|
||||
"previewSize": {
|
||||
|
||||
11
application/Espo/Resources/i18n/en_US/AppSecret.json
Normal file
11
application/Espo/Resources/i18n/en_US/AppSecret.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"labels": {
|
||||
"Create AppSecret": "Create Secret"
|
||||
},
|
||||
"fields": {
|
||||
"value": "Value"
|
||||
},
|
||||
"tooltips": {
|
||||
"name": "Allowed characters:\n* `[a-z]`\n* `[A-Z]`\n* `[0-9]`\n* `_`"
|
||||
}
|
||||
}
|
||||
@@ -63,7 +63,8 @@
|
||||
"WorkingTimeRange": "Working Time Exception",
|
||||
"AuthenticationProvider": "Authentication Provider",
|
||||
"GlobalStream": "Global Stream",
|
||||
"AddressCountry": "Address Country"
|
||||
"AddressCountry": "Address Country",
|
||||
"AppSecret": "App Secret"
|
||||
},
|
||||
"scopeNamesPlural": {
|
||||
"Note": "Notes",
|
||||
@@ -117,7 +118,8 @@
|
||||
"WorkingTimeRange": "Working Time Exceptions",
|
||||
"AuthenticationProvider": "Authentication Providers",
|
||||
"GlobalStream": "Global Stream",
|
||||
"AddressCountry": "Address Countries"
|
||||
"AddressCountry": "Address Countries",
|
||||
"AppSecret": "App Secrets"
|
||||
},
|
||||
"labels": {
|
||||
"Previous Page": "Previous Page",
|
||||
|
||||
13
application/Espo/Resources/layouts/AppSecret/detail.json
Normal file
13
application/Espo/Resources/layouts/AppSecret/detail.json
Normal file
@@ -0,0 +1,13 @@
|
||||
[
|
||||
{
|
||||
"rows": [
|
||||
[{"name": "name"}, false],
|
||||
[{"name": "value"}]
|
||||
]
|
||||
},
|
||||
{
|
||||
"rows": [
|
||||
[{"name": "description"}]
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,13 @@
|
||||
[
|
||||
{
|
||||
"rows": [
|
||||
[{"name": "name"}],
|
||||
[{"name": "value"}]
|
||||
]
|
||||
},
|
||||
{
|
||||
"rows": [
|
||||
[{"name": "description"}]
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1 @@
|
||||
[]
|
||||
10
application/Espo/Resources/layouts/AppSecret/list.json
Normal file
10
application/Espo/Resources/layouts/AppSecret/list.json
Normal file
@@ -0,0 +1,10 @@
|
||||
[
|
||||
{
|
||||
"name": "name",
|
||||
"link": true
|
||||
},
|
||||
{
|
||||
"name": "description",
|
||||
"width": 50
|
||||
}
|
||||
]
|
||||
@@ -338,6 +338,12 @@
|
||||
"iconClass": "fas fa-phone",
|
||||
"description": "phoneNumbers"
|
||||
},
|
||||
{
|
||||
"url": "#Admin/appSecrets",
|
||||
"label": "App Secrets",
|
||||
"iconClass": "fas fa-key",
|
||||
"description": "appSecrets"
|
||||
},
|
||||
{
|
||||
"url": "#Admin/appLog",
|
||||
"label": "App Log",
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"controller": "controllers/record",
|
||||
"mergeDisabled": true,
|
||||
"exportDisabled": true,
|
||||
"massUpdateDisabled": true
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"fields": {
|
||||
"value": {
|
||||
"internal": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"fields": {
|
||||
"name": {
|
||||
"type": "varchar",
|
||||
"maxLength": 100,
|
||||
"required": true,
|
||||
"pattern": "[a-zA-Z]{1}[a-zA-Z0-9_]+",
|
||||
"index": true,
|
||||
"tooltip": true
|
||||
},
|
||||
"value": {
|
||||
"type": "text",
|
||||
"required": true,
|
||||
"view": "views/admin/app-secret/fields/value"
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "datetime",
|
||||
"readOnly": true
|
||||
},
|
||||
"modifiedAt": {
|
||||
"type": "datetime",
|
||||
"readOnly": true
|
||||
},
|
||||
"createdBy": {
|
||||
"type": "link",
|
||||
"readOnly": true
|
||||
},
|
||||
"modifiedBy": {
|
||||
"type": "link",
|
||||
"readOnly": true
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
"createdBy": {
|
||||
"type": "belongsTo",
|
||||
"entity": "User"
|
||||
},
|
||||
"modifiedBy": {
|
||||
"type": "belongsTo",
|
||||
"entity": "User"
|
||||
}
|
||||
},
|
||||
"collection": {
|
||||
"orderBy": "name",
|
||||
"order": "asc",
|
||||
"textFilterFields": ["name"]
|
||||
},
|
||||
"indexes": {
|
||||
"nameDeleteId": {
|
||||
"type": "unique",
|
||||
"columns": [
|
||||
"name",
|
||||
"deleteId"
|
||||
]
|
||||
}
|
||||
},
|
||||
"deleteId": true
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"createInputFilterClassNameList": [
|
||||
"Espo\\Classes\\Record\\AppSecret\\ValueInputFilter"
|
||||
],
|
||||
"updateInputFilterClassNameList": [
|
||||
"Espo\\Classes\\Record\\AppSecret\\ValueInputFilter"
|
||||
],
|
||||
"duplicateWhereBuilderClassName": "Espo\\Classes\\DuplicateWhereBuilders\\General"
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"entity": true,
|
||||
"layouts": false,
|
||||
"tab": false,
|
||||
"acl": false,
|
||||
"customizable": false,
|
||||
"duplicateCheckFieldList": ["name"]
|
||||
}
|
||||
64
application/Espo/Tools/AppSecret/SecretProvider.php
Normal file
64
application/Espo/Tools/AppSecret/SecretProvider.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2024 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Tools\AppSecret;
|
||||
|
||||
use Espo\Core\Utils\Crypt;
|
||||
use Espo\Entities\AppSecret;
|
||||
use Espo\ORM\EntityManager;
|
||||
|
||||
/**
|
||||
* @since 8.5.0
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
class SecretProvider
|
||||
{
|
||||
public function __construct(
|
||||
private Crypt $crypt,
|
||||
private EntityManager $entityManager,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Get an app secret value
|
||||
* @param string $name A secret name.
|
||||
*/
|
||||
public function get(string $name): ?string
|
||||
{
|
||||
$secret = $this->entityManager
|
||||
->getRDBRepositoryByClass(AppSecret::class)
|
||||
->where(['name' => $name])
|
||||
->findOne();
|
||||
|
||||
if (!$secret) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->crypt->decrypt($secret->getValue());
|
||||
}
|
||||
}
|
||||
@@ -394,6 +394,11 @@ class AdminController extends Controller {
|
||||
});
|
||||
}
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
actionAppSecrets() {
|
||||
this.getRouter().dispatch('AppSecret', 'list', {fromAdmin: true});
|
||||
}
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
actionJobs() {
|
||||
this.collectionFactory.create('Job', collection => {
|
||||
|
||||
80
client/src/views/admin/app-secret/fields/value.js
Normal file
80
client/src/views/admin/app-secret/fields/value.js
Normal file
@@ -0,0 +1,80 @@
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2024 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
import TextFieldView from 'views/fields/text';
|
||||
|
||||
export default class extends TextFieldView {
|
||||
|
||||
detailTemplateContent = `**********`
|
||||
|
||||
validations = ['required']
|
||||
|
||||
changingMode = false
|
||||
|
||||
data() {
|
||||
return {
|
||||
isNew: this.model.isNew(),
|
||||
...super.data(),
|
||||
};
|
||||
}
|
||||
|
||||
afterRenderEdit() {
|
||||
super.afterRenderEdit();
|
||||
|
||||
if (!this.model.isNew() && !this.changingMode) {
|
||||
this.element.innerHTML = '';
|
||||
|
||||
const a = document.createElement('a');
|
||||
a.role = 'button';
|
||||
a.onclick = () => this.changePassword();
|
||||
a.textContent = this.translate('change');
|
||||
|
||||
this.element.appendChild(a);
|
||||
}
|
||||
}
|
||||
|
||||
onDetailModeSet() {
|
||||
this.changingMode = false;
|
||||
|
||||
return super.onDetailModeSet();
|
||||
}
|
||||
|
||||
fetch() {
|
||||
if (!this.model.isNew() && !this.changingMode) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return super.fetch();
|
||||
}
|
||||
|
||||
async changePassword() {
|
||||
this.changingMode = true;
|
||||
|
||||
await this.reRender();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user