Merge branch 'master' of https://github.com/espocrm/espocrm
This commit is contained in:
@@ -219,7 +219,7 @@ class DataManager
|
||||
|
||||
$cryptKey = $config->get('cryptKey');
|
||||
if (!$cryptKey) {
|
||||
$cryptKey = \Espo\Core\Utils\Util::generateKey();
|
||||
$cryptKey = \Espo\Core\Utils\Util::generateSecretKey();
|
||||
$config->set('cryptKey', $cryptKey);
|
||||
}
|
||||
|
||||
|
||||
@@ -97,6 +97,6 @@ class Crypt
|
||||
|
||||
public function generateKey()
|
||||
{
|
||||
return \Espo\Core\Utils\Util::generateKey();
|
||||
return \Espo\Core\Utils\Util::generateSecretKey();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -556,28 +556,35 @@ class Util
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function generateId()
|
||||
public static function generateId() : string
|
||||
{
|
||||
return uniqid() . substr(md5(rand()), 0, 4);
|
||||
}
|
||||
|
||||
public static function generateApiKey()
|
||||
public static function generateMoreEntropyId() : string
|
||||
{
|
||||
return substr(md5(uniqid(rand(), true)), 0, 16) . substr(md5(rand()), 0, 4);
|
||||
}
|
||||
|
||||
public static function generateCryptId() : string
|
||||
{
|
||||
if (!function_exists('random_bytes')) {
|
||||
return self::generateId();
|
||||
return self::generateMoreEntropyId();
|
||||
}
|
||||
return bin2hex(random_bytes(16));
|
||||
}
|
||||
|
||||
public static function generateSecretKey()
|
||||
public static function generateApiKey() : string
|
||||
{
|
||||
if (!function_exists('random_bytes')) {
|
||||
return self::generateId();
|
||||
}
|
||||
return bin2hex(random_bytes(16));
|
||||
return self::generateCryptId();
|
||||
}
|
||||
|
||||
public static function generateKey()
|
||||
public static function generateSecretKey() : string
|
||||
{
|
||||
return self::generateCryptId();
|
||||
}
|
||||
|
||||
public static function generateKey() : string
|
||||
{
|
||||
return md5(uniqid(rand(), true));
|
||||
}
|
||||
|
||||
@@ -31,6 +31,8 @@ namespace Espo\Entities;
|
||||
|
||||
class UniqueId extends \Espo\Core\ORM\Entity
|
||||
{
|
||||
|
||||
public function getIdValue() : ?string
|
||||
{
|
||||
return $this->get('name');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -83,18 +83,17 @@ class MassEmail extends \Espo\Services\Record
|
||||
{
|
||||
parent::afterDeleteEntity($massEmail);
|
||||
|
||||
$this->cleanupQueueItems($massEmail);
|
||||
$this->getEntityManager()->getMapper('RDB')->massDeleteFromDb('EmailQueueItem', [
|
||||
'massEmailId' => $massEmail->id,
|
||||
]);
|
||||
}
|
||||
|
||||
protected function cleanupQueueItems(Entity $massEmail)
|
||||
{
|
||||
$existingQueueItemList = $this->getEntityManager()->getRepository('EmailQueueItem')->select(['id'])->where([
|
||||
'status' => ['Pending', 'Failed'],
|
||||
$this->getEntityManager()->getMapper('RDB')->massDeleteFromDb('EmailQueueItem', [
|
||||
'massEmailId' => $massEmail->id,
|
||||
])->find();
|
||||
foreach ($existingQueueItemList as $existingQueueItem) {
|
||||
$this->getEntityManager()->getMapper('RDB')->deleteFromDb('EmailQueueItem', $existingQueueItem->id);
|
||||
}
|
||||
'status' => ['Pending', 'Failed'],
|
||||
]);
|
||||
}
|
||||
|
||||
public function createQueue(Entity $massEmail, $isTest = false, $additionalTargetList = [])
|
||||
|
||||
@@ -1061,6 +1061,33 @@ abstract class Mapper implements IMapper
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mass delete from database by specified whereClause.
|
||||
* @return Number of deleted records or null if failure.
|
||||
*/
|
||||
public function massDeleteFromDb(string $entityType, array $whereClause) : ?int
|
||||
{
|
||||
$table = $this->toDb($entityType);
|
||||
|
||||
$sql = "DELETE FROM `{$table}`";
|
||||
|
||||
$entity = $this->entityFactory->create($entityType);
|
||||
if (!$entity) return null;
|
||||
|
||||
$wherePart = $this->query->getWhere($entity, $whereClause);
|
||||
if ($wherePart) {
|
||||
$sql .= ' WHERE ' . $wherePart;
|
||||
}
|
||||
|
||||
$sth = $this->pdo->prepare($sql);
|
||||
|
||||
if ($sth->execute()) {
|
||||
return $sth->rowCount();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function restoreDeleted(string $entityType, $id)
|
||||
{
|
||||
if (empty($entityType) || empty($id)) return false;
|
||||
|
||||
@@ -44,7 +44,7 @@ class UniqueId extends \Espo\Core\ORM\Repositories\RDB
|
||||
public function getNew() : ?Entity
|
||||
{
|
||||
$entity = parent::getNew();
|
||||
$entity->set('name', \Espo\Core\Utils\Util::generateId());
|
||||
$entity->set('name', \Espo\Core\Utils\Util::generateMoreEntropyId());
|
||||
return $entity;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ class Webhook extends \Espo\Core\ORM\Repositories\RDB
|
||||
|
||||
protected function fillSecretKey(Entity $entity)
|
||||
{
|
||||
$secretKey = \Espo\Core\Utils\Util::generateKey();
|
||||
$secretKey = \Espo\Core\Utils\Util::generateSecretKey();
|
||||
$entity->set('secretKey', $secretKey);
|
||||
}
|
||||
|
||||
|
||||
@@ -245,7 +245,7 @@ class User extends Record
|
||||
throw new Forbidden(json_encode(['reason' => 'Already-Sent']));
|
||||
}
|
||||
|
||||
$requestId = Util::generateId() . Util::generateKey();
|
||||
$requestId = Util::generateCryptId();
|
||||
|
||||
$passwordChangeRequest = $this->getEntityManager()->getEntity('PasswordChangeRequest');
|
||||
$passwordChangeRequest->set([
|
||||
@@ -411,7 +411,7 @@ class User extends Record
|
||||
$entity->set('apiKey', $apiKey);
|
||||
|
||||
if ($entity->get('authMethod') === 'Hmac') {
|
||||
$secretKey = \Espo\Core\Utils\Util::generateKey();
|
||||
$secretKey = \Espo\Core\Utils\Util::generateSecretKey();
|
||||
$entity->set('secretKey', $secretKey);
|
||||
}
|
||||
|
||||
@@ -508,7 +508,7 @@ class User extends Record
|
||||
$entity->set('apiKey', $apiKey);
|
||||
|
||||
if ($entity->get('authMethod') === 'Hmac') {
|
||||
$secretKey = \Espo\Core\Utils\Util::generateKey();
|
||||
$secretKey = \Espo\Core\Utils\Util::generateSecretKey();
|
||||
$entity->set('secretKey', $secretKey);
|
||||
}
|
||||
}
|
||||
@@ -559,7 +559,7 @@ class User extends Record
|
||||
|
||||
if ($entity->isApi()) {
|
||||
if ($entity->isAttributeChanged('authMethod') && $entity->get('authMethod') === 'Hmac') {
|
||||
$secretKey = \Espo\Core\Utils\Util::generateKey();
|
||||
$secretKey = \Espo\Core\Utils\Util::generateSecretKey();
|
||||
$entity->set('secretKey', $secretKey);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ table.table {
|
||||
.list-kanban > div > table > thead,
|
||||
.list-group-panel,
|
||||
.popup-notification {
|
||||
.box-shadow(2px 2px 4px rgba(0,0,0,0.13));
|
||||
.box-shadow(2px 2px 4px rgba(0,0,0,0.09));
|
||||
}
|
||||
|
||||
.stick-sub.button-container {
|
||||
|
||||
@@ -302,4 +302,37 @@ class MapperTest extends \tests\integration\Core\BaseTestCase
|
||||
$isRelated = $em->getRepository('Lead')->isRelated($l1, 'createdAccount', $a1);
|
||||
$this->assertFalse($isRelated);
|
||||
}
|
||||
|
||||
public function testMassDeleteFromDb1()
|
||||
{
|
||||
$app = $this->createApplication();
|
||||
$em = $app->getContainer()->get('entityManager');
|
||||
$mapper = $em->getMapper('RDB');
|
||||
|
||||
$a1 = $em->createEntity('Account', [
|
||||
'name' => '1',
|
||||
]);
|
||||
$a2 = $em->createEntity('Account', [
|
||||
'name' => '2',
|
||||
]);
|
||||
|
||||
$count = $mapper->massDeleteFromDb('Account', [
|
||||
'name' => '1',
|
||||
]);
|
||||
|
||||
$this->assertEquals(1, $count);
|
||||
|
||||
$a1 = $em->getEntity('Account', $a1->id);
|
||||
$this->assertNull($a1);
|
||||
|
||||
$a2 = $em->getEntity('Account', $a2->id);
|
||||
$this->assertNotNull($a2);
|
||||
|
||||
|
||||
$count = $mapper->massDeleteFromDb('Account', [
|
||||
'name' => '3',
|
||||
]);
|
||||
|
||||
$this->assertEquals(0, $count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -490,4 +490,32 @@ class DBMapperTest extends \PHPUnit\Framework\TestCase
|
||||
));
|
||||
}
|
||||
|
||||
public function testMassDeleteFromDb()
|
||||
{
|
||||
$query = "DELETE FROM `post` WHERE post.name = 'test' AND post.deleted = '1'";
|
||||
|
||||
$sth = $this->getMockBuilder('\\PDOStatement')->disableOriginalConstructor()->getMock();
|
||||
|
||||
$this->pdo
|
||||
->expects($this->once())
|
||||
->method('prepare')
|
||||
->with($query)
|
||||
->will($this->returnValue($sth));
|
||||
|
||||
$sth
|
||||
->expects($this->once())
|
||||
->method('execute')
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$sth
|
||||
->expects($this->once())
|
||||
->method('rowCount')
|
||||
->will($this->returnValue(1));
|
||||
|
||||
|
||||
$this->db->massDeleteFromDb('Post', [
|
||||
'name' => 'test',
|
||||
'deleted' => true,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user