mirror of https://github.com/MISP/MISP
638 lines
25 KiB
PHP
638 lines
25 KiB
PHP
<?php
|
|
App::uses('AppModel', 'Model');
|
|
App::uses('ServerSyncTool', 'Tools');
|
|
|
|
class AnalystData extends AppModel
|
|
{
|
|
|
|
public $recursive = -1;
|
|
|
|
public $actsAs = array(
|
|
'Containable'
|
|
);
|
|
|
|
public $valid_targets = [
|
|
'Attribute',
|
|
'Event',
|
|
'EventReport',
|
|
'GalaxyCluster',
|
|
'Galaxy',
|
|
'Object',
|
|
'Note',
|
|
'Opinion',
|
|
'Relationship',
|
|
'Organisation',
|
|
'SharingGroup'
|
|
];
|
|
|
|
const NOTE = 0,
|
|
OPINION = 1,
|
|
RELATIONSHIP = 2;
|
|
|
|
const ANALYST_DATA_TYPES = [
|
|
'Note',
|
|
'Opinion',
|
|
'Relationship',
|
|
];
|
|
|
|
/** @var object|null */
|
|
protected $Note;
|
|
/** @var object|null */
|
|
protected $Opinion;
|
|
/** @var object|null */
|
|
protected $Relationship;
|
|
/** @var object|null */
|
|
protected $ObjectRelationship;
|
|
/** @var object|null */
|
|
protected $User;
|
|
/** @var object|null */
|
|
public $Org;
|
|
/** @var object|null */
|
|
public $Orgc;
|
|
/** @var object|null */
|
|
public $SharingGroup;
|
|
|
|
public $current_user = null;
|
|
|
|
public $belongsTo = [
|
|
'SharingGroup' => [
|
|
'className' => 'SharingGroup',
|
|
'foreignKey' => 'sharing_group_id'
|
|
],
|
|
];
|
|
|
|
public function __construct($id = false, $table = null, $ds = null)
|
|
{
|
|
parent::__construct($id, $table, $ds);
|
|
$this->bindModel([
|
|
'belongsTo' => [
|
|
'Org' => [
|
|
'className' => 'Organisation',
|
|
'foreignKey' => false,
|
|
'conditions' => [
|
|
sprintf('%s.org_uuid = Org.uuid', $this->alias)
|
|
],
|
|
],
|
|
'Orgc' => [
|
|
'className' => 'Organisation',
|
|
'foreignKey' => false,
|
|
'conditions' => [
|
|
sprintf('%s.orgc_uuid = Orgc.uuid', $this->alias)
|
|
],
|
|
],
|
|
'SharingGroup' => [
|
|
'className' => 'SharingGroup',
|
|
'foreignKey' => false,
|
|
'conditions' => [
|
|
sprintf('%s.sharing_group_id = SharingGroup.id', $this->alias)
|
|
],
|
|
],
|
|
]
|
|
]);
|
|
$this->Org = ClassRegistry::init('Organisation');
|
|
$this->Orgc = ClassRegistry::init('Organisation');
|
|
}
|
|
|
|
public function afterFind($results, $primary = false)
|
|
{
|
|
parent::afterFind($results, $primary);
|
|
|
|
$this->setUser();
|
|
|
|
foreach ($results as $i => $v) {
|
|
$results[$i][$this->alias]['note_type'] = $this->current_type_id;
|
|
$results[$i][$this->alias]['note_type_name'] = $this->current_type;
|
|
|
|
$results[$i] = $this->rearrangeOrganisation($results[$i], $this->current_user);
|
|
$results[$i] = $this->rearrangeSharingGroup($results[$i], $this->current_user);
|
|
|
|
$results[$i][$this->alias]['_canEdit'] = $this->canEditAnalystData($this->current_user, $v, $this->alias);
|
|
|
|
if (!empty($this->fetchRecursive) && !empty($results[$i][$this->alias]['uuid'])) {
|
|
$results[$i][$this->alias] = $this->fetchChildNotesAndOpinions($this->current_user, $results[$i][$this->alias]);
|
|
}
|
|
}
|
|
return $results;
|
|
}
|
|
|
|
public function beforeValidate($options = array())
|
|
{
|
|
parent::beforeValidate();
|
|
if (empty($this->id) && empty($this->data[$this->current_type]['uuid'])) {
|
|
$this->data[$this->current_type]['uuid'] = CakeText::uuid();
|
|
}
|
|
if (empty($this->id)) {
|
|
if (empty($this->data[$this->current_type]['orgc_uuid']) || empty($this->current_user['Role']['perm_sync'])) {
|
|
$this->data[$this->current_type]['orgc_uuid'] = $this->current_user['Organisation']['uuid'];
|
|
}
|
|
$this->data[$this->current_type]['org_uuid'] = $this->current_user['Organisation']['uuid'];
|
|
$this->data[$this->current_type]['authors'] = $this->current_user['email'];
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Checks if user can modify given analyst data
|
|
*
|
|
* @param array $user
|
|
* @param array $analystData
|
|
* @return bool
|
|
*/
|
|
public function canEditAnalystData(array $user, array $analystData, $modelType): bool
|
|
{
|
|
if (!isset($analystData[$modelType])) {
|
|
throw new InvalidArgumentException('Passed object does not contain a(n) ' . $modelType);
|
|
}
|
|
if ($user['Role']['perm_site_admin']) {
|
|
return true;
|
|
}
|
|
if (isset($analystData[$modelType]['orgc_uuid']) && $analystData[$modelType]['orgc_uuid'] == $user['Organisation']['uuid']) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public function buildConditions(array $user): array
|
|
{
|
|
$conditions = [];
|
|
if (!$user['Role']['perm_site_admin']) {
|
|
$sgids = $this->SharingGroup->authorizedIds($user);
|
|
$alias = $this->alias;
|
|
$conditions['AND']['OR'] = [
|
|
"{$alias}.org_uuid" => $user['Organisation']['uuid'],
|
|
[
|
|
'AND' => [
|
|
"{$alias}.distribution >" => 0,
|
|
"{$alias}.distribution <" => 4
|
|
],
|
|
],
|
|
[
|
|
'AND' => [
|
|
"{$alias}.sharing_group_id" => $sgids,
|
|
"{$alias}.distribution" => 4
|
|
]
|
|
]
|
|
];
|
|
}
|
|
return $conditions;
|
|
}
|
|
|
|
protected function setUser()
|
|
{
|
|
if (empty($this->current_user)) {
|
|
$user_id = Configure::read('CurrentUserId');
|
|
$this->User = ClassRegistry::init('User');
|
|
if ($user_id) {
|
|
$this->current_user = $this->User->getAuthUser($user_id);
|
|
}
|
|
}
|
|
}
|
|
|
|
private function rearrangeOrganisation(array $analystData): array
|
|
{
|
|
if (!empty($analystData[$this->alias]['orgc_uuid'])) {
|
|
if (!isset($analystData['Orgc'])) {
|
|
$analystData[$this->alias]['Orgc'] = $this->Orgc->find('first', ['conditions' => ['uuid' => $analystData[$this->alias]['orgc_uuid']]])['Organisation'];
|
|
} else {
|
|
$analystData[$this->alias]['Orgc'] = $analystData['Orgc'];
|
|
}
|
|
unset($analystData['Orgc']);
|
|
}
|
|
if (!empty($analystData[$this->alias]['org_uuid'])) {
|
|
if (!isset($analystData['Org'])) {
|
|
$analystData[$this->alias]['Org'] = $this->Org->find('first', ['conditions' => ['uuid' => $analystData[$this->alias]['org_uuid']]])['Organisation'];
|
|
} else {
|
|
$analystData[$this->alias]['Org'] = $analystData['Org'];
|
|
}
|
|
unset($analystData['Org']);
|
|
}
|
|
return $analystData;
|
|
}
|
|
|
|
private function rearrangeSharingGroup(array $analystData, array $user): array
|
|
{
|
|
if (isset($analystData[$this->alias]['distribution'])) {
|
|
if ($analystData[$this->alias]['distribution'] == 4) {
|
|
if (!isset($analystData['SharingGroup'])) {
|
|
$this->SharingGroup = ClassRegistry::init('SharingGroup');
|
|
$sg = $this->SharingGroup->fetchSG($analystData[$this->alias]['sharing_group_id'], $user, true);
|
|
$analystData[$this->alias]['SharingGroup'] = $sg['SharingGroup'];
|
|
} else {
|
|
$analystData[$this->alias]['SharingGroup'] = $analystData['SharingGroup'];
|
|
}
|
|
} else {
|
|
unset($analystData['SharingGroup']);
|
|
}
|
|
}
|
|
return $analystData;
|
|
}
|
|
|
|
public function deduceType(string $uuid)
|
|
{
|
|
foreach ($this->valid_targets as $valid_target) {
|
|
$this->{$valid_target} = ClassRegistry::init($valid_target);
|
|
$result = $this->$valid_target->find('first', [
|
|
'conditions' => [$valid_target.'.uuid' => $uuid],
|
|
'recursive' => -1
|
|
]);
|
|
if (!empty($result)) {
|
|
return $valid_target;
|
|
}
|
|
}
|
|
throw new NotFoundException(__('Invalid UUID'));
|
|
}
|
|
|
|
public function deduceAnalystDataType(array $analystData)
|
|
{
|
|
foreach (self::ANALYST_DATA_TYPES as $type) {
|
|
if (isset($analystData[$type])) {
|
|
return $type;
|
|
}
|
|
}
|
|
throw new NotFoundException(__('Invalid or could not deduce analyst data type'));
|
|
}
|
|
|
|
public function fetchChildNotesAndOpinions(array $user, array $analystData): array
|
|
{
|
|
$this->Note = ClassRegistry::init('Note');
|
|
$this->Opinion = ClassRegistry::init('Opinion');
|
|
$paramsNote = [
|
|
'recursive' => -1,
|
|
'contain' => ['Org', 'Orgc'],
|
|
'conditions' => [
|
|
'AND' => [
|
|
$this->buildConditions($user)
|
|
],
|
|
'object_type' => $this->current_type,
|
|
'object_uuid' => $analystData['uuid'],
|
|
]
|
|
];
|
|
$paramsOpinion = [
|
|
'recursive' => -1,
|
|
'contain' => ['Org', 'Orgc'],
|
|
'conditions' => [
|
|
'AND' => [
|
|
$this->buildConditions($user)
|
|
],
|
|
'object_type' => $this->current_type,
|
|
'object_uuid' => $analystData['uuid'],
|
|
]
|
|
];
|
|
|
|
// recursively fetch and include nested notes and opinions
|
|
$childNotes = array_map(function ($item) use ($user) {
|
|
$expandedNotes = $this->fetchChildNotesAndOpinions($user, $item[$this->Note->current_type]);
|
|
return $expandedNotes;
|
|
}, $this->Note->find('all', $paramsNote));
|
|
$childOpinions = array_map(function ($item) use ($user) {
|
|
$expandedNotes = $this->fetchChildNotesAndOpinions($user, $item[$this->Opinion->current_type]);
|
|
return $expandedNotes;
|
|
}, $this->Opinion->find('all', $paramsOpinion));
|
|
|
|
if (!empty($childNotes)) {
|
|
$analystData[$this->Note->current_type] = $childNotes;
|
|
}
|
|
if (!empty($childOpinions)) {
|
|
$analystData[$this->Opinion->current_type] = $childOpinions;
|
|
}
|
|
return $analystData;
|
|
}
|
|
|
|
public function getExistingRelationships()
|
|
{
|
|
$existingRelationships = $this->find('column', [
|
|
'recursive' => -1,
|
|
'fields' => ['relationship_type'],
|
|
'unique' => true,
|
|
]);
|
|
$this->ObjectRelationship = ClassRegistry::init('ObjectRelationship');
|
|
$objectRelationships = $this->ObjectRelationship->find('column', [
|
|
'recursive' => -1,
|
|
'fields' => ['name'],
|
|
'unique' => true,
|
|
]);
|
|
return array_unique(array_merge($existingRelationships, $objectRelationships));
|
|
}
|
|
|
|
/**
|
|
* Gets a cluster then save it.
|
|
*
|
|
* @param array $user
|
|
* @param array $analystData Analyst data to be saved
|
|
* @param bool $fromPull If the current capture is performed from a PULL sync
|
|
* @param int $orgId The organisation id that should own the analyst data
|
|
* @param array $server The server for which to capture is ongoing
|
|
* @return array Result of the capture including successes, fails and errors
|
|
*/
|
|
public function captureAnalystData(array $user, array $analystData, $fromPull=false, $orgUUId=false, $server=false): array
|
|
{
|
|
$results = ['success' => false, 'imported' => 0, 'ignored' => 0, 'failed' => 0, 'errors' => []];
|
|
$type = $this->deduceAnalystDataType($analystData);
|
|
$analystModel = ClassRegistry::init($type);
|
|
|
|
if ($fromPull && !empty($orgUUId)) {
|
|
$analystData[$type]['org_uuid'] = $orgUUId;
|
|
} else {
|
|
$analystData[$type]['org_uuid'] = $user['Organisation']['uuid'];
|
|
}
|
|
|
|
$this->AnalystDataBlocklist = ClassRegistry::init('AnalystDataBlocklist');
|
|
if ($this->AnalystDataBlocklist->checkIfBlocked($analystData[$type]['uuid'])) {
|
|
$results['errors'][] = __('Blocked by blocklist');
|
|
$results['ignored']++;
|
|
return $results;
|
|
}
|
|
|
|
if (!isset($analystData[$type]['orgc_uuid']) && !isset($cluster['Orgc'])) {
|
|
$analystData[$type]['orgc_uuid'] = $analystData[$type]['org_uuid'];
|
|
} else {
|
|
if (!isset($analystData[$type]['Orgc'])) {
|
|
if (isset($analystData[$type]['orgc_uuid']) && $analystData[$type]['orgc_uuid'] != $user['Organisation']['uuid'] && !$user['Role']['perm_sync'] && !$user['Role']['perm_site_admin']) {
|
|
$analystData[$type]['orgc_uuid'] = $analystData[$type]['org_uuid']; // Only sync user can create analyst data on behalf of other users
|
|
}
|
|
} else {
|
|
if ($analystData[$type]['Orgc']['uuid'] != $user['Organisation']['uuid'] && !$user['Role']['perm_sync'] && !$user['Role']['perm_site_admin']) {
|
|
$analystData[$type]['orgc_uuid'] = $analystData[$type]['org_uuid']; // Only sync user can create analyst data on behalf of other users
|
|
}
|
|
}
|
|
if (isset($analystData[$type]['orgc_uuid']) && $analystData[$type]['orgc_uuid'] != $user['Organisation']['uuid'] && !$user['Role']['perm_sync'] && !$user['Role']['perm_site_admin']) {
|
|
$analystData[$type]['orgc_uuid'] = $analystData[$type]['org_uuid']; // Only sync user can create analyst data on behalf of other users
|
|
}
|
|
}
|
|
|
|
if (!Configure::check('MISP.enableOrgBlocklisting') || Configure::read('MISP.enableOrgBlocklisting') !== false) {
|
|
$analystModel->OrgBlocklist = ClassRegistry::init('OrgBlocklist');
|
|
if (!isset($analystData[$type]['Orgc']['uuid'])) {
|
|
$orgc = $analystModel->Orgc->find('first', ['conditions' => ['Orgc.uuid' => $analystData[$type]['orgc_uuid']], 'fields' => ['Orgc.uuid'], 'recursive' => -1]);
|
|
} else {
|
|
$orgc = ['Orgc' => ['uuid' => $analystData[$type]['Orgc']['uuid']]];
|
|
}
|
|
if ($analystData[$type]['orgc_uuid'] != 0 && $analystModel->OrgBlocklist->hasAny(array('OrgBlocklist.org_uuid' => $orgc['Orgc']['uuid']))) {
|
|
$results['errors'][] = __('Organisation blocklisted (%s)', $orgc['Orgc']['uuid']);
|
|
$results['ignored']++;
|
|
return $results;
|
|
}
|
|
}
|
|
|
|
$analystData = $analystModel->captureOrganisationAndSG($analystData, $type, $user);
|
|
$existingAnalystData = $analystModel->find('first', [
|
|
'conditions' => ["{$type}.uuid" => $analystData[$type]['uuid'],],
|
|
]);
|
|
if (!isset($analystData[$type]['distribution'])) {
|
|
$analystData[$type]['distribution'] = Configure::read('MISP.default_event_distribution'); // use default event distribution
|
|
}
|
|
if ($analystData[$type]['distribution'] != 4) {
|
|
$analystData[$type]['sharing_group_id'] = null;
|
|
}
|
|
if (empty($existingAnalystData)) {
|
|
unset($analystData[$type]['id']);
|
|
$analystModel->create();
|
|
$saveSuccess = $analystModel->save($analystData);
|
|
} else {
|
|
if (!$existingAnalystData[$type]['locked'] && empty($server['Server']['internal'])) {
|
|
$results['errors'][] = __('Blocked an edit to an analyst data that was created locally. This can happen if a synchronised analyst data that was created on this instance was modified by an administrator on the remote side.');
|
|
$results['failed']++;
|
|
return $results;
|
|
}
|
|
if ($analystData[$type]['modified'] > $existingAnalystData[$type]['modified']) {
|
|
$analystData[$type]['id'] = $existingAnalystData[$type]['id'];
|
|
$saveSuccess = $analystModel->save($analystData);
|
|
} else {
|
|
$results['errors'][] = __('Remote version is not newer than local one for analyst data (%s)', $analystData[$type]['uuid']);
|
|
$results['ignored']++;
|
|
return $results;
|
|
}
|
|
}
|
|
if ($saveSuccess) {
|
|
$results['imported']++;
|
|
$analystModel->find('first', [
|
|
'conditions' => ['uuid' => $analystData[$type]['uuid']],
|
|
'recursive' => -1
|
|
]);
|
|
} else {
|
|
$results['failed']++;
|
|
foreach ($analystModel->validationErrors as $validationError) {
|
|
$results['errors'][] = $validationError[0];
|
|
}
|
|
}
|
|
$results['success'] = $results['imported'] > 0;
|
|
return $results;
|
|
}
|
|
|
|
public function captureOrganisationAndSG($element, $model, $user)
|
|
{
|
|
$this->Event = ClassRegistry::init('Event');
|
|
if (isset($element[$model]['distribution']) && $element[$model]['distribution'] == 4) {
|
|
$element[$model] = $this->Event->captureSGForElement($element[$model], $user);
|
|
}
|
|
// first we want to see how the creator organisation is encoded
|
|
// The options here are either by passing an organisation object along or simply passing a string along
|
|
if (isset($element[$model]['Orgc'])) {
|
|
$element[$model]['orgc_uuid'] = $this->Orgc->captureOrg($element[$model]['Orgc'], $user, false, true);
|
|
unset($element[$model]['Orgc']);
|
|
} else {
|
|
// Can't capture the Orgc, default to the current user
|
|
$element[$model]['orgc_uuid'] = $user['Organisation']['uuid'];
|
|
}
|
|
return $element;
|
|
}
|
|
|
|
/**
|
|
* Push Analyst Data to remote server.
|
|
* @param array $user
|
|
* @param ServerSyncTool $serverSync
|
|
* @return array
|
|
* @throws Exception
|
|
*/
|
|
public function pushAnalystData(array $user, ServerSyncTool $serverSync): array
|
|
{
|
|
$server = $serverSync->server();
|
|
|
|
if (!$server['Server']['push_analyst_data']) {
|
|
return [];
|
|
}
|
|
$this->Server = ClassRegistry::init('Server');
|
|
$this->AnalystData = ClassRegistry::init('AnalystData');
|
|
|
|
$this->log("Starting Analyst Data sync with server #{$server['Server']['id']}", LOG_INFO);
|
|
|
|
$analystData = $this->getElligibleDataToPush($user);
|
|
$keyedAnalystData = [];
|
|
foreach ($analystData as $type => $entries) {
|
|
foreach ($entries as $entry) {
|
|
$entry = $entry[$type];
|
|
$keyedAnalystData[$type][$entry['uuid']] = $entry['modified'];
|
|
}
|
|
}
|
|
if (empty($analystData)) {
|
|
return [];
|
|
}
|
|
|
|
try {
|
|
$conditions = [];
|
|
foreach ($keyedAnalystData as $model => $entry) {
|
|
$conditions[$model] = array_keys($entry);
|
|
}
|
|
$analystDataToPush = $this->Server->getElligibleDataIdsFromServerForPush($serverSync, $analystData, $conditions);
|
|
} catch (Exception $e) {
|
|
$this->logException("Could not get eligible Analyst Data IDs from server #{$server['Server']['id']} for push.", $e);
|
|
return [];
|
|
}
|
|
$successes = [];
|
|
foreach ($analystDataToPush as $model => $entries) {
|
|
foreach ($entries as $entry) {
|
|
$result = $this->AnalystData->uploadEntryToServer($model, $entry, $server, $serverSync, $user);
|
|
if ($result === 'Success') {
|
|
$successes[] = __('AnalystData %s', $entry['GalaxyCluster']['uuid']);
|
|
}
|
|
}
|
|
}
|
|
return $successes;
|
|
}
|
|
|
|
/**
|
|
* Collect elligible data to be pushed on a server
|
|
*
|
|
* @param array $user
|
|
* @return array
|
|
*/
|
|
public function getElligibleDataToPush(array $user): array
|
|
{
|
|
$options = [
|
|
'recursive' => -1,
|
|
'conditions' => [
|
|
$this->buildConditions($user),
|
|
],
|
|
];
|
|
return $this->getAllAnalystData('all', $options);
|
|
}
|
|
|
|
public function filterAnalystDataForPush($allIncomingAnalystData): array
|
|
{
|
|
$validModels = [
|
|
'Note' => ClassRegistry::init('Note'),
|
|
'Opinion' => ClassRegistry::init('Opinion'),
|
|
'Relationship' => ClassRegistry::init('Relationship'),
|
|
];
|
|
|
|
|
|
$allData = ['Note' => [], 'Opinion' => [], 'Relationship' => []];
|
|
foreach ($allIncomingAnalystData as $model => $entries) {
|
|
$incomingAnalystData = $entries;
|
|
$incomingUuids = array_keys($entries);
|
|
$options = [
|
|
'conditions' => ["{$model}.uuid" => $incomingUuids],
|
|
'recursive' => -1,
|
|
'fields' => ['uuid', 'modified', 'locked']
|
|
];
|
|
$analystData = $validModels[$model]->find('all', $options);
|
|
foreach ($analystData as $entry) {
|
|
if (strtotime($entry[$model]['modified']) >= strtotime($incomingAnalystData[$entry[$model]['uuid']])) {
|
|
unset($incomingAnalystData[$entry[$model]['uuid']]);
|
|
continue;
|
|
}
|
|
if ($entry[$model]['locked'] == 0) {
|
|
unset($incomingAnalystData[$entry[$model]['uuid']]);
|
|
}
|
|
}
|
|
$allData[$model] = $incomingAnalystData;
|
|
}
|
|
return $allData;
|
|
}
|
|
|
|
/**
|
|
* getAllAnalystData Collect all analyst data regardless if they are notes, opinions or relationships
|
|
*
|
|
* @param array $user
|
|
* @return array
|
|
*/
|
|
public function getAllAnalystData($findType='all', array $findOptions=[]): array
|
|
{
|
|
$allData = [];
|
|
$this->Note = ClassRegistry::init('Note');
|
|
$this->Opinion = ClassRegistry::init('Opinion');
|
|
$this->Relationship = ClassRegistry::init('Relationship');
|
|
$validModels = [$this->Note, $this->Opinion, $this->Relationship];
|
|
foreach ($validModels as $model) {
|
|
$result = $model->find($findType, $findOptions);
|
|
$allData[$model->alias] = $result;
|
|
}
|
|
return $allData;
|
|
}
|
|
|
|
public function uploadEntryToServer($type, array $analystData, array $server, ServerSyncTool $serverSync, array $user)
|
|
{
|
|
$analystDataID = $analystData[$type]['id'];
|
|
$analystData = $this->prepareForPushToServer($type, $analystData, $server);
|
|
if (is_numeric($analystData)) {
|
|
return $analystData;
|
|
}
|
|
|
|
try {
|
|
if (!$serverSync->isSupported(ServerSyncTool::PERM_SYNC) || !$serverSync->isSupported(ServerSyncTool::PERM_ANALYST_DATA)) {
|
|
return __('The remote user does not have the permission to manipulate analyst data, the upload of the analyst data has been blocked.');
|
|
}
|
|
$serverSync->pushAnalystData($type, $analystData)->json();
|
|
} catch (Exception $e) {
|
|
$title = __('Uploading AnalystData (%s::%s) to Server (%s)', $type, $analystDataID, $server['Server']['id']);
|
|
$this->loadLog()->createLogEntry($user, 'push', 'AnalystData', $analystDataID, $title, $e->getMessage());
|
|
|
|
$this->logException("Could not push analyst data to remote server {$serverSync->serverId()}", $e);
|
|
return $e->getMessage();
|
|
}
|
|
|
|
return 'Success';
|
|
}
|
|
|
|
private function prepareForPushToServer($type, array $analystData, array $server)
|
|
{
|
|
if ($analystData[$type]['distribution'] == 4) {
|
|
if (!empty($analystData[$type]['SharingGroup']['SharingGroupServer'])) {
|
|
$found = false;
|
|
foreach ($analystData[$type]['SharingGroup']['SharingGroupServer'] as $sgs) {
|
|
if ($sgs['server_id'] == $server['Server']['id']) {
|
|
$found = true;
|
|
}
|
|
}
|
|
if (!$found) {
|
|
return 403;
|
|
}
|
|
} elseif (empty($analystData[$type]['SharingGroup']['roaming'])) {
|
|
return 403;
|
|
}
|
|
}
|
|
$this->Event = ClassRegistry::init('Event');
|
|
if ($this->Event->checkDistributionForPush($analystData, $server, $type)) {
|
|
return $this->updateAnalystDataForSync($type, $analystData, $server);
|
|
}
|
|
return 403;
|
|
}
|
|
|
|
private function updateAnalystDataForSync($type, array $analystData, array $server): array
|
|
{
|
|
$this->Event = ClassRegistry::init('Event');
|
|
// cleanup the array from things we do not want to expose
|
|
foreach (['id'] as $field) {
|
|
unset($analystData[$type][$field]);
|
|
}
|
|
// Add the local server to the list of instances in the SG
|
|
if (isset($analystData[$type]['SharingGroup']) && isset($analystData[$type]['SharingGroup']['SharingGroupServer'])) {
|
|
foreach ($analystData[$type]['SharingGroup']['SharingGroupServer'] as &$s) {
|
|
if ($s['server_id'] == 0) {
|
|
$s['Server'] = array(
|
|
'id' => 0,
|
|
'url' => $this->Event->__getAnnounceBaseurl(),
|
|
'name' => $this->Event->__getAnnounceBaseurl()
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Downgrade the event from connected communities to community only
|
|
if (!$server['Server']['internal'] && $analystData[$type]['distribution'] == 2) {
|
|
$analystData[$type]['distribution'] = 1;
|
|
}
|
|
return $analystData;
|
|
}
|
|
}
|