mirror of https://github.com/MISP/MISP
637 lines
27 KiB
PHP
637 lines
27 KiB
PHP
<?php
|
|
App::uses('AppModel', 'Model');
|
|
App::uses('ConnectionManager', 'Model');
|
|
App::uses('FileAccessTool', 'Tools');
|
|
|
|
/**
|
|
* @property Event $Event
|
|
*/
|
|
class Organisation extends AppModel
|
|
{
|
|
public $useTable = 'organisations';
|
|
|
|
public $recursive = -1;
|
|
|
|
public $actsAs = array(
|
|
'AuditLog',
|
|
'Containable',
|
|
'SysLogLogable.SysLogLogable' => array( // TODO Audit, logable
|
|
'roleModel' => 'Organisation',
|
|
'roleKey' => 'organisation_id',
|
|
'change' => 'full'
|
|
),
|
|
);
|
|
|
|
private $__orgCache = array();
|
|
|
|
public $validate = array(
|
|
'name' => array(
|
|
'unique' => array(
|
|
'rule' => 'isUnique',
|
|
'message' => 'An organisation with this name already exists.'
|
|
),
|
|
'valueNotEmpty' => array(
|
|
'rule' => array('valueNotEmpty'),
|
|
),
|
|
),
|
|
'uuid' => array(
|
|
'unique' => array(
|
|
'rule' => 'isUnique',
|
|
'message' => 'An organisation with this UUID already exists.',
|
|
'on' => 'create',
|
|
),
|
|
'uuid' => array(
|
|
'rule' => 'uuid',
|
|
'message' => 'Please provide a valid RFC 4122 UUID',
|
|
'allowEmpty' => true
|
|
),
|
|
'valueNotEmpty' => array(
|
|
'rule' => array('valueNotEmpty'),
|
|
)
|
|
)
|
|
);
|
|
|
|
public $hasMany = array(
|
|
'User' => array(
|
|
'className' => 'User',
|
|
'foreignKey' => 'org_id'
|
|
),
|
|
'SharingGroupOrg' => array(
|
|
'className' => 'SharingGroupOrg',
|
|
'foreignKey' => 'org_id',
|
|
'dependent'=> true,
|
|
),
|
|
'SharingGroup' => array(
|
|
'className' => 'SharingGroup',
|
|
'foreignKey' => 'org_id',
|
|
),
|
|
'Event' => array(
|
|
'className' => 'Event',
|
|
'foreignKey' => 'orgc_id',
|
|
),
|
|
'EventOwned' => array(
|
|
'className' => 'Event',
|
|
'foreignKey' => 'org_id',
|
|
),
|
|
);
|
|
|
|
const ORGANISATION_ASSOCIATIONS = array(
|
|
'AccessLog' => array('table' => 'access_logs', 'fields' => array('org_id')),
|
|
'AuditLog' => array('table' => 'audit_logs', 'fields' => array('org_id')),
|
|
'Correlation' => array('table' => 'correlations', 'fields' => array('org_id')),
|
|
'Cerebrate' => array('table' => 'cerebrates', 'fields' => array('org_id')),
|
|
'Dashboard' => array('table' => 'dashboards', 'fields' => array('restrict_to_org_id')),
|
|
'Event' => array('table' => 'events', 'fields' => array('org_id', 'orgc_id')),
|
|
'EventGraph' => array('table' => 'event_graph', 'fields' => array('org_id')),
|
|
'Feed' => array('table' => 'feeds', 'fields' => array('orgc_id')),
|
|
'GalaxyCluster' => array('table' => 'galaxy_clusters', 'fields' => array('org_id', 'orgc_id')),
|
|
'ObjectTemplate' => array('table' => 'object_templates', 'fields' => array('org_id')),
|
|
'Job' => array('table' => 'jobs', 'fields' => array('org_id')),
|
|
'RestClientHistory' => array('table' => 'rest_client_histories', 'fields' => array('org_id')),
|
|
'Server' => array('table' => 'servers', 'fields' => array('org_id', 'remote_org_id')),
|
|
'ShadowAttribute' => array('table' => 'shadow_attributes', 'fields' => array('org_id', 'event_org_id')),
|
|
'SharingGroup' => array('table' => 'sharing_groups', 'fields' => array('org_id')),
|
|
'SharingGroupOrg' => array('table' => 'sharing_group_orgs', 'fields' => array('org_id')),
|
|
'SharingGroupBlueprint' => array('table' => 'sharing_group_blueprints', 'fields' => array('org_id')),
|
|
'Sighting' => array('table' => 'sightings', 'fields' => array('org_id')),
|
|
'SightingdbOrg' => array('table' => 'sightingdb_orgs', 'fields' => array('org_id')),
|
|
'Thread' => array('table' => 'threads', 'fields' => array('org_id')),
|
|
'Tag' => array('table' => 'tags', 'fields' => array('org_id')),
|
|
'TagCollection' => array('table' => 'tag_collections', 'fields' => array('org_id')),
|
|
'User' => array('table' => 'users', 'fields' => array('org_id'))
|
|
);
|
|
|
|
const GENERIC_MISP_ORGANISATION = [
|
|
'id' => '0',
|
|
'name' => 'MISP',
|
|
'date_created' => '',
|
|
'date_modified' => '',
|
|
'description' => 'Automatically generated MISP organisation',
|
|
'type' => '',
|
|
'nationality' => 'Not specified',
|
|
'sector' => '',
|
|
'created_by' => '0',
|
|
'uuid' => '0',
|
|
'contacts' => '',
|
|
'local' => true,
|
|
'restricted_to_domain' => [],
|
|
'landingpage' => null
|
|
];
|
|
|
|
public function beforeValidate($options = array())
|
|
{
|
|
parent::beforeValidate();
|
|
$org = &$this->data[$this->alias];
|
|
if (empty($org['uuid'])) {
|
|
$org['uuid'] = CakeText::uuid();
|
|
} else {
|
|
$org['uuid'] = strtolower(trim($org['uuid']));
|
|
}
|
|
$date = date('Y-m-d H:i:s');
|
|
if (array_key_exists('restricted_to_domain', $org)) {
|
|
if (!is_array($org['restricted_to_domain'])) {
|
|
$org['restricted_to_domain'] = str_replace("\r", '', $org['restricted_to_domain']);
|
|
$org['restricted_to_domain'] = explode("\n", $org['restricted_to_domain']);
|
|
}
|
|
|
|
$org['restricted_to_domain'] = array_values(
|
|
array_filter(
|
|
array_map('trim', $org['restricted_to_domain'])
|
|
)
|
|
);
|
|
|
|
$org['restricted_to_domain'] = json_encode($org['restricted_to_domain']);
|
|
}
|
|
if (!isset($org['id'])) {
|
|
$org['date_created'] = $date;
|
|
}
|
|
$org['date_modified'] = $date;
|
|
if (empty($org['nationality'])) {
|
|
$org['nationality'] = '';
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public function beforeDelete($cascade = false)
|
|
{
|
|
if ($this->User->find('count', array('conditions' => array('User.org_id' => $this->id))) != 0) {
|
|
return false;
|
|
}
|
|
if ($this->Event->find('count', array('conditions' => array('OR' => array('Event.org_id' => $this->id, 'Event.orgc_id' => $this->id)))) != 0) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public function afterSave($created, $options = array())
|
|
{
|
|
if ($this->pubToZmq('organisation')) {
|
|
$pubSubTool = $this->getPubSubTool();
|
|
$pubSubTool->modified($this->data, 'organisation');
|
|
}
|
|
$action = $created ? 'add' : 'edit';
|
|
$this->publishKafkaNotification('organisation', $this->data, $action);
|
|
return true;
|
|
}
|
|
|
|
public function afterFind($results, $primary = false)
|
|
{
|
|
foreach ($results as $k => $organisation) {
|
|
if (!empty($organisation['Organisation']['restricted_to_domain'])) {
|
|
$results[$k]['Organisation']['restricted_to_domain'] = json_decode($organisation['Organisation']['restricted_to_domain'], true);
|
|
foreach ($results[$k]['Organisation']['restricted_to_domain'] as $k2 => $v) {
|
|
$results[$k]['Organisation']['restricted_to_domain'][$k2] = trim($v);
|
|
}
|
|
} else if (isset($organisation['Organisation']['restricted_to_domain'])){
|
|
$results[$k]['Organisation']['restricted_to_domain'] = array();
|
|
}
|
|
}
|
|
return $results;
|
|
}
|
|
|
|
/**
|
|
* @param array|string $org
|
|
* @param array $user
|
|
* @param bool $force
|
|
* @return int Organisation ID
|
|
* @throws Exception
|
|
*/
|
|
public function captureOrg($org, array $user, $force = false)
|
|
{
|
|
$fieldsToFetch = $force ?
|
|
['id', 'uuid', 'type', 'date_created', 'date_modified', 'nationality', 'sector', 'contacts'] :
|
|
['id', 'uuid'];
|
|
|
|
if (is_array($org)) {
|
|
if (!empty($org['uuid'])) {
|
|
$conditions = array('uuid' => $org['uuid']);
|
|
$uuid = $org['uuid'];
|
|
} else {
|
|
$conditions = array('name' => $org['name']);
|
|
}
|
|
$name = $org['name'];
|
|
} else {
|
|
$conditions = array('name' => $org);
|
|
$name = $org;
|
|
}
|
|
|
|
$existingOrg = $this->find('first', array(
|
|
'recursive' => -1,
|
|
'conditions' => $conditions,
|
|
'fields' => $fieldsToFetch,
|
|
));
|
|
if (empty($existingOrg)) {
|
|
$organisation = array(
|
|
'name' => $name,
|
|
'local' => 0,
|
|
'created_by' => $user['id'],
|
|
);
|
|
// If we have the UUID set, then we have only made sure that the org doesn't exist by UUID
|
|
// We want to create a new organisation for pushed data, even if the same org name exists
|
|
// Alter the name if the name is already taken by a random string
|
|
if (isset($uuid)) {
|
|
$existingOrgByName = $this->hasAny(['name' => $name]);
|
|
if ($existingOrgByName) {
|
|
$organisation['name'] = $organisation['name'] . '_' . mt_rand(0, 9999);
|
|
}
|
|
$organisation['uuid'] = $uuid;
|
|
}
|
|
$this->create();
|
|
$this->save($organisation);
|
|
return $this->id;
|
|
} else {
|
|
$changed = false;
|
|
if (isset($org['uuid']) && empty($existingOrg[$this->alias]['uuid'])) {
|
|
$existingOrg[$this->alias]['uuid'] = $org['uuid'];
|
|
$changed = true;
|
|
}
|
|
if ($force) {
|
|
$fields = array('type', 'date_created', 'date_modified', 'nationality', 'sector', 'contacts');
|
|
foreach ($fields as $field) {
|
|
if (isset($org[$field])) {
|
|
if ($existingOrg[$this->alias][$field] != $org[$field]) {
|
|
$existingOrg[$this->alias][$field] = $org[$field];
|
|
if ($field !== 'date_modified') {
|
|
$changed = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ($changed) {
|
|
$this->save($existingOrg);
|
|
}
|
|
}
|
|
return $existingOrg[$this->alias]['id'];
|
|
}
|
|
|
|
/**
|
|
* @param string $name Organisation name
|
|
* @param int $userId Organisation creator
|
|
* @param bool $local True if organisation should be marked as local
|
|
* @param string|null $uuid UUID of newly created org
|
|
* @return int Existing or newly created organisation ID
|
|
* @throws Exception
|
|
*/
|
|
public function createOrgFromName($name, $userId, $local, $uuid = null)
|
|
{
|
|
$existingOrg = $this->find('first', [
|
|
'recursive' => -1,
|
|
'conditions' => ['name' => $name],
|
|
'fields' => ['id'],
|
|
]);
|
|
if (empty($existingOrg)) {
|
|
$this->create();
|
|
$organisation = [
|
|
'name' => $name,
|
|
'local' => $local,
|
|
'created_by' => $userId,
|
|
];
|
|
if ($uuid) {
|
|
$organisation['uuid'] = $uuid;
|
|
}
|
|
if (!$this->save($organisation)) {
|
|
throw new Exception("Could not create new org $name");
|
|
}
|
|
return $this->id;
|
|
}
|
|
return $existingOrg[$this->alias]['id'];
|
|
}
|
|
|
|
public function orgMerge($id, $request, $user)
|
|
{
|
|
$currentOrg = $this->find('first', array('recursive' => -1, 'conditions' => array('Organisation.id' => $id)));
|
|
if (isset($currentOrg['Organisation']['restricted_to_domain'])) {
|
|
$currentOrg['Organisation']['restricted_to_domain'] = json_encode($currentOrg['Organisation']['restricted_to_domain']);
|
|
}
|
|
$currentOrgUserCount = $this->User->find('count', array(
|
|
'conditions' => array('User.org_id' => $id)
|
|
));
|
|
$targetOrgId = $request['Organisation']['targetType'] == 0 ? $request['Organisation']['orgsLocal'] : $request['Organisation']['orgsExternal'];
|
|
$targetOrg = $this->find(
|
|
'first',
|
|
array(
|
|
'recursive' => -1,
|
|
'conditions' => array('Organisation.id' => $targetOrgId)
|
|
)
|
|
);
|
|
if (empty($currentOrg) || empty($targetOrg)) {
|
|
throw new MethodNotAllowedException('Something went wrong with the organisation merge. Organisation not found.');
|
|
}
|
|
$dir = new Folder();
|
|
$this->Log = ClassRegistry::init('Log');
|
|
$dirPath = APP . 'tmp' . DS . 'logs' . DS . 'merges';
|
|
if (!$dir->create($dirPath)) {
|
|
throw new MethodNotAllowedException('Merge halted because the log directory (default: /var/www/MISP/app/tmp/logs/merges) could not be created. This is most likely a permission issue, make sure that MISP can write to the logs directory and try again.');
|
|
}
|
|
$logFile = new File($dirPath . DS . 'merge_' . $currentOrg['Organisation']['id'] . '_' . $targetOrg['Organisation']['id'] . '_' . time() . '.log');
|
|
if (!$logFile->create()) {
|
|
throw new MethodNotAllowedException('Merge halted because the log file (default location: /var/www/MISP/app/tmp/logs/merges/[old_org_id]_[new_org_id]_timestamp.log) could not be created. This is most likely a permission issue, make sure that MISP can write to the logs directory and try again.');
|
|
}
|
|
$backupFile = new File($dirPath . DS . 'merge_' . $currentOrg['Organisation']['id'] . '_' . $targetOrg['Organisation']['id'] . '_' . time() . '.sql');
|
|
if (!$backupFile->create()) {
|
|
throw new MethodNotAllowedException('Merge halted because the backup script file (default location: /var/www/MISP/app/tmp/logs/merges/[old_org_id]_[new_org_id]_timestamp.sql) could not be created. This is most likely a permission issue, make sure that MISP can write to the logs directory and try again.');
|
|
}
|
|
if ($this->isMysql()) {
|
|
$sql = 'INSERT INTO organisations (`' . implode('`, `', array_keys($currentOrg['Organisation'])) . '`) VALUES (\'' . implode('\', \'', array_values($currentOrg['Organisation'])) . '\');';
|
|
} else {
|
|
$sql = 'INSERT INTO organisations ("' . implode('", "', array_keys($currentOrg['Organisation'])) . '") VALUES (\'' . implode('\', \'', array_values($currentOrg['Organisation'])) . '\');';
|
|
}
|
|
$backupFile->append($sql . PHP_EOL);
|
|
$this->Log->create();
|
|
$this->Log->saveOrFailSilently(array(
|
|
'org' => $user['Organisation']['name'],
|
|
'model' => 'Organisation',
|
|
'model_id' => $currentOrg['Organisation']['id'],
|
|
'email' => $user['email'],
|
|
'action' => 'merge',
|
|
'user_id' => $user['id'],
|
|
'title' => 'Starting merger of ' . $currentOrg['Organisation']['name'] . '(' . $currentOrg['Organisation']['id'] . ') into ' . $targetOrg['Organisation']['name'] . '(' . $targetOrg['Organisation']['name'] . ')',
|
|
'change' => '',
|
|
));
|
|
$dataMoved = array('removed_org' => $currentOrg);
|
|
$success = true;
|
|
foreach (self::ORGANISATION_ASSOCIATIONS as $model => $data) {
|
|
foreach ($data['fields'] as $field) {
|
|
if ($this->isMysql()) {
|
|
$sql = 'SELECT `id` FROM `' . $data['table'] . '` WHERE `' . $field . '` = "' . $currentOrg['Organisation']['id'] . '"';
|
|
} else {
|
|
$sql = 'SELECT "id" FROM "' . $data['table'] . '" WHERE "' . $field . '" = "' . $currentOrg['Organisation']['id'] . '"';
|
|
}
|
|
$temp = $this->query($sql);
|
|
if (!empty($temp)) {
|
|
$dataMoved['values_changed'][$model][$field] = Set::extract('/' . $data['table'] . '/id', $temp);
|
|
if (!empty($dataMoved['values_changed'][$model][$field])) {
|
|
$this->Log->create();
|
|
try {
|
|
if ($this->isMysql()) {
|
|
$sql = 'UPDATE `' . $data['table'] . '` SET `' . $field . '` = ' . $targetOrg['Organisation']['id'] . ' WHERE `' . $field . '` = ' . $currentOrg['Organisation']['id'] . ';';
|
|
} else {
|
|
$sql = 'UPDATE "' . $data['table'] . '" SET "' . $field . '" = ' . $targetOrg['Organisation']['id'] . ' WHERE "' . $field . '" = ' . $currentOrg['Organisation']['id'] . ';';
|
|
}
|
|
$result = $this->query($sql);
|
|
if ($this->isMysql()) {
|
|
$sql = 'UPDATE `' . $data['table'] . '` SET `' . $field . '` = ' . $currentOrg['Organisation']['id'] . ' WHERE `id` IN (' . implode(',', $dataMoved['values_changed'][$model][$field]) . ');';
|
|
} else {
|
|
$sql = 'UPDATE "' . $data['table'] . '" SET "' . $field . '" = ' . $currentOrg['Organisation']['id'] . ' WHERE "id" IN (' . implode(',', $dataMoved['values_changed'][$model][$field]) . ');';
|
|
}
|
|
$backupFile->append($sql . PHP_EOL);
|
|
$this->Log->saveOrFailSilently(array(
|
|
'org' => $user['Organisation']['name'],
|
|
'model' => 'Organisation',
|
|
'model_id' => $currentOrg['Organisation']['id'],
|
|
'email' => $user['email'],
|
|
'action' => 'merge',
|
|
'user_id' => $user['id'],
|
|
'title' => 'Update for ' . $model . '.' . $field . ' has completed successfully.',
|
|
'change' => '',
|
|
));
|
|
} catch (Exception $e) {
|
|
$this->Log->saveOrFailSilently(array(
|
|
'org' => $user['Organisation']['name'],
|
|
'model' => 'Organisation',
|
|
'model_id' => $currentOrg['Organisation']['id'],
|
|
'email' => $user['email'],
|
|
'action' => 'merge',
|
|
'user_id' => $user['id'],
|
|
'title' => 'Update for ' . $model . '.' . $field . ' has failed.',
|
|
'change' => json_encode($e->getMessage()),
|
|
));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ($success) {
|
|
$updateTargetOrg = false;
|
|
if ($currentOrgUserCount > 0 && $currentOrg['Organisation']['local'] && !$targetOrg['Organisation']['local']) {
|
|
$targetOrg['Organisation']['local'] = 1;
|
|
$updateTargetOrg = true;
|
|
}
|
|
if (strlen($targetOrg['Organisation']['name']) > strlen($currentOrg['Organisation']['name']) && strpos($targetOrg['Organisation']['name'], $currentOrg['Organisation']['name']) === 0) {
|
|
$temp = substr($targetOrg['Organisation']['name'], strlen($currentOrg['Organisation']['name']));
|
|
if (preg_match('/^\_[0-9]+$/i', $temp)) {
|
|
$targetOrg['Organisation']['name'] = $currentOrg['Organisation']['name'];
|
|
$updateTargetOrg = true;
|
|
}
|
|
}
|
|
if (!file_exists(APP . 'webroot/img/orgs/' . $targetOrgId . '.png') && file_exists(APP . 'webroot/img/orgs/' . $id . '.png')) {
|
|
rename(APP . 'webroot/img/orgs/' . $id . '.png', APP . 'webroot/img/orgs/' . $targetOrgId . '.png');
|
|
}
|
|
$this->delete($currentOrg['Organisation']['id']);
|
|
if ($updateTargetOrg) {
|
|
$this->save($targetOrg);
|
|
}
|
|
$success = $targetOrgId;
|
|
}
|
|
$backupFile->close();
|
|
$logFile->write(json_encode($dataMoved));
|
|
$logFile->close();
|
|
return $success;
|
|
}
|
|
|
|
public function fetchOrg($id)
|
|
{
|
|
if (empty($id)) {
|
|
return false;
|
|
}
|
|
$conditions = array('Organisation.id' => $id);
|
|
if (Validation::uuid($id)) {
|
|
$conditions = array('Organisation.uuid' => $id);
|
|
} elseif (!is_numeric($id)) {
|
|
$conditions = array('LOWER(Organisation.name)' => strtolower($id));
|
|
}
|
|
$org = $this->find('first', array(
|
|
'conditions' => $conditions,
|
|
'recursive' => -1
|
|
));
|
|
return (empty($org)) ? false : $org[$this->alias];
|
|
}
|
|
|
|
/**
|
|
* Attach organisations to evnet
|
|
* @param array $data
|
|
* @param array $fields
|
|
* @return array
|
|
*/
|
|
public function attachOrgs($data, $fields)
|
|
{
|
|
$event = $data['Event'];
|
|
$toFetch = [];
|
|
if (!isset($this->__orgCache[$event['orgc_id']])) {
|
|
$toFetch[] = $event['orgc_id'];
|
|
}
|
|
if (!isset($this->__orgCache[$event['org_id']]) && $event['org_id'] != $event['orgc_id']) {
|
|
$toFetch[] = $event['org_id'];
|
|
}
|
|
if (!empty($toFetch)) {
|
|
$orgs = $this->find('all', array(
|
|
'conditions' => array('id' => $toFetch),
|
|
'recursive' => -1,
|
|
'fields' => $fields,
|
|
));
|
|
foreach ($orgs as $org) {
|
|
$this->__orgCache[$org[$this->alias]['id']] = $org[$this->alias];
|
|
}
|
|
}
|
|
$data['Orgc'] = $this->__orgCache[$event['orgc_id']];
|
|
$data['Org'] = $this->__orgCache[$event['org_id']];
|
|
return $data;
|
|
}
|
|
|
|
public function getOrgIdsFromMeta($metaConditions)
|
|
{
|
|
$orgIds = $this->find('column', array(
|
|
'conditions' => $metaConditions,
|
|
'fields' => array('id'),
|
|
'recursive' => -1
|
|
));
|
|
if (empty($orgIds)) {
|
|
return array(-1);
|
|
}
|
|
return $orgIds;
|
|
}
|
|
|
|
public function checkDesiredOrg($suggestedOrg, $registration)
|
|
{
|
|
if ($suggestedOrg !== false && $suggestedOrg !== -1) {
|
|
$conditions = array();
|
|
if (!empty($registration['Inbox']['data']['org_uuid'])) {
|
|
$conditions = array('Organisation.uuid' => $registration['Inbox']['data']['org_uuid']);
|
|
} else if (!empty($registration['Inbox']['data']['org_name'])) {
|
|
$conditions = array('Organisation.name' => $registration['Inbox']['data']['org_name']);
|
|
} else {
|
|
$domain = explode('@', $registration['Inbox']['data']['email'])[1];
|
|
$conditions = array('LOWER(Organisation.name)' => strtolower($domain));
|
|
}
|
|
$identifiedOrg = $this->User->Organisation->find('first', array(
|
|
'recursive' => -1,
|
|
'fields' => array('id', 'name', 'local'),
|
|
'conditions' => $conditions
|
|
));
|
|
if (empty($identifiedOrg)) {
|
|
$suggestedOrg = -1;
|
|
} else if (!empty($suggestedOrg) && $suggestedOrg[0] !== $identifiedOrg['Organisation']['id']) {
|
|
$suggestedOrg = false;
|
|
} else {
|
|
$suggestedOrg = array($identifiedOrg['Organisation']['id'], $identifiedOrg['Organisation']['name'], $identifiedOrg['Organisation']['local']);
|
|
}
|
|
}
|
|
return $suggestedOrg;
|
|
}
|
|
|
|
/**
|
|
* Hide organisation view from users if they haven't yet contributed data and Security.hide_organisation_index_from_users is enabled
|
|
*
|
|
* @see Organisation::canSee if you want to check multiple orgs
|
|
* @param array $user
|
|
* @param int $orgId
|
|
* @return bool
|
|
*/
|
|
public function canSee(array $user, $orgId)
|
|
{
|
|
if ($user['org_id'] == $orgId) {
|
|
return true; // User can see his own org.
|
|
}
|
|
if (!$user['Role']['perm_sharing_group'] && Configure::read('Security.hide_organisation_index_from_users')) {
|
|
// Check if there is event from given org that can current user see
|
|
$eventConditions = $this->Event->createEventConditions($user);
|
|
$eventConditions['AND']['Event.orgc_id'] = $orgId;
|
|
$event = $this->Event->hasAny($eventConditions);
|
|
if (!$event) {
|
|
$proposalConditions = $this->Event->ShadowAttribute->buildConditions($user);
|
|
$proposalConditions['AND']['ShadowAttribute.org_id'] = $orgId;
|
|
$proposal = $this->Event->ShadowAttribute->find('first', array(
|
|
'fields' => array('ShadowAttribute.id'),
|
|
'recursive' => -1,
|
|
'conditions' => $proposalConditions,
|
|
'contain' => ['Event', 'Attribute'],
|
|
));
|
|
if (empty($proposal)) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Create conditions for fetching orgs based on user permission.
|
|
* @see Organisation::canSee if you want to check just one org
|
|
* @param array $user
|
|
* @return array|array[]
|
|
*/
|
|
public function createConditions(array $user)
|
|
{
|
|
if (!$user['Role']['perm_sharing_group'] && Configure::read('Security.hide_organisation_index_from_users')) {
|
|
$eventConditions = $this->Event->createEventConditions($user);
|
|
$allowedOrgs = $this->Event->find('column', [
|
|
'fields' => ['Event.orgc_id'],
|
|
'conditions' => $eventConditions,
|
|
'unique' => true,
|
|
]);
|
|
$allowedOrgs[] = $user['org_id'];
|
|
|
|
$proposalConditions = $this->Event->ShadowAttribute->buildConditions($user);
|
|
// Do not check orgs that we already can see
|
|
$proposalConditions['AND'][]['NOT'] = ['ShadowAttribute.org_id' => $allowedOrgs];
|
|
$orgsWithProposal = $this->Event->ShadowAttribute->find('column', [
|
|
'fields' => ['ShadowAttribute.org_id'],
|
|
'conditions' => $proposalConditions,
|
|
'contain' => ['Event', 'Attribute'],
|
|
'unique' => true,
|
|
'order' => false,
|
|
]);
|
|
|
|
$allowedOrgs = array_merge($allowedOrgs, $orgsWithProposal);
|
|
return ['AND' => ['id' => $allowedOrgs]];
|
|
}
|
|
|
|
return [];
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
private function getCountryGalaxyCluster()
|
|
{
|
|
static $list;
|
|
if (!$list) {
|
|
try {
|
|
$content = FileAccessTool::readJsonFromFile(APP . '/files/misp-galaxy/clusters/country.json');
|
|
$list = $content['values'];
|
|
} catch (Exception $e) {
|
|
$this->logException("MISP Galaxy are not updated, countries will not be available.", $e, LOG_WARNING);
|
|
$list = [];
|
|
}
|
|
}
|
|
return $list;
|
|
}
|
|
|
|
/**
|
|
* @param string $countryName
|
|
* @return string|null
|
|
*/
|
|
public function getCountryCode($countryName)
|
|
{
|
|
foreach ($this->getCountryGalaxyCluster() as $country) {
|
|
if ($country['description'] === $countryName) {
|
|
return $country['meta']['ISO'];
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* @return string[]
|
|
*/
|
|
public function getCountries()
|
|
{
|
|
$countries = array_column($this->getCountryGalaxyCluster(), 'description');
|
|
sort($countries);
|
|
array_unshift($countries, 'International');
|
|
array_unshift($countries, 'Europe');
|
|
return $countries;
|
|
}
|
|
}
|