2016-12-05 00:47:34 +01:00
< ? php
App :: uses ( 'AppModel' , 'Model' );
2018-07-19 11:48:22 +02:00
class GalaxyCluster extends AppModel
{
public $useTable = 'galaxy_clusters' ;
2016-12-05 00:47:34 +01:00
2018-07-19 11:48:22 +02:00
public $recursive = - 1 ;
2016-12-05 00:47:34 +01:00
2018-07-19 11:48:22 +02:00
public $actsAs = array (
'Containable' ,
);
2016-12-05 00:47:34 +01:00
2018-07-19 11:48:22 +02:00
public $validate = array (
);
2016-12-05 00:47:34 +01:00
2018-07-19 11:48:22 +02:00
public $belongsTo = array (
'Galaxy' => array (
'className' => 'Galaxy' ,
'foreignKey' => 'galaxy_id' ,
),
'Tag' => array (
'foreignKey' => false ,
'conditions' => array ( 'GalaxyCluster.tag_name = Tag.name' )
)
);
2016-12-05 00:47:34 +01:00
2018-11-23 14:11:33 +01:00
private $__clusterCache = array ();
2016-12-09 07:58:03 +01:00
2018-07-19 11:48:22 +02:00
public $hasMany = array (
'GalaxyElement' => array ( 'dependent' => true ),
2019-02-10 13:08:12 +01:00
// 'GalaxyReference'
2018-07-19 11:48:22 +02:00
);
2016-12-05 00:47:34 +01:00
2018-07-19 11:48:22 +02:00
public function beforeValidate ( $options = array ())
{
parent :: beforeValidate ();
if ( ! isset ( $this -> data [ 'GalaxyCluster' ][ 'description' ])) {
$this -> data [ 'GalaxyCluster' ][ 'description' ] = '' ;
}
return true ;
}
2016-12-05 00:47:34 +01:00
2018-07-19 11:48:22 +02:00
public function afterFind ( $results , $primary = false )
{
foreach ( $results as $k => $result ) {
if ( isset ( $results [ $k ][ 'GalaxyCluster' ][ 'authors' ])) {
$results [ $k ][ 'GalaxyCluster' ][ 'authors' ] = json_decode ( $results [ $k ][ 'GalaxyCluster' ][ 'authors' ], true );
}
}
return $results ;
}
2016-12-05 00:47:34 +01:00
2018-07-19 11:48:22 +02:00
public function beforeDelete ( $cascade = true )
{
$this -> GalaxyElement -> deleteAll ( array ( 'GalaxyElement.galaxy_cluster_id' => $this -> id ));
}
2018-01-26 19:49:54 +01:00
2016-12-09 07:58:03 +01:00
2018-07-19 11:48:22 +02:00
// receive a full galaxy and add all new clusters, update existing ones contained in the new galaxy, cull old clusters that are removed from the galaxy
public function update ( $id , $galaxy )
{
$existingClusters = $this -> find ( 'all' , array (
'conditions' => array ( 'GalaxyCluster.galaxy_id' => $id ),
'recursive' => - 1 ,
));
foreach ( $galaxy [ 'values' ] as $cluster ) {
$oldCluster = false ;
if ( ! empty ( $existingClusters )) {
foreach ( $existingClusters as $k => $existingCluster ) {
if ( $existingCluster [ 'GalaxyCluster' ][ 'value' ] == $cluster [ 'value' ]) {
$oldCluster = true ;
if ( $cluster [ 'description' ] != $existingCluster [ 'GalaxyCluster' ][ 'description' ]) {
$existingCluster [ 'GalaxyCluster' ][ 'description' ] = $cluster [ 'description' ];
$this -> GalaxyElement -> deleteAll ( 'galaxy_cluster_id' == $existingCluster [ 'GalaxyCluster' ][ 'id' ]);
$this -> save ( $existingCluster );
$template = array ( 'galaxy_cluster_id' => $this -> id );
$toSave = array ();
foreach ( $cluster as $key => $value ) {
if ( in_array ( $key , array ( 'value' , 'description' ))) {
continue ;
}
$tosave [] = array_merge ( $template , array ( 'key' => $key , 'value' => $value ));
}
$this -> GalaxyElement -> saveMany ( $toSave );
}
unset ( $existingClusters [ $k ]);
}
}
}
if ( ! $oldCluster ) {
$newCluster = array_intersect_key ( $cluster , array_flip ( array ( 'value' , 'description' )));
$newCluster [ 'galaxy_id' ] = $id ;
$newCluster [ 'type' ] = $galaxy [ 'type' ];
2018-11-23 14:11:33 +01:00
$newCluster [ 'collection_uuid' ] = $newCluster [ 'uuid' ];
2018-07-19 11:48:22 +02:00
$toSave [] = $newCluster ;
}
$final = array ();
if ( ! empty ( $existingCluster )) {
$fieldsToUpdate = array ( 'description' , '' );
$final = $existingCluster ;
}
}
$this -> saveMany ( $toSave );
// Let's retrieve the full list of clusters we have for the given galaxy and pass it to the element system
$existingClusters = $this -> find ( 'all' , array (
'conditions' => array ( 'GalaxyCluster.galaxy_id' ),
'contain' => array ( 'GalaxyElement' /*, 'GalaxyReference'*/ )
));
$this -> GalaxyElement -> update ( $id , $existingClusters , $galaxy [ 'values' ]);
}
2016-12-09 07:58:03 +01:00
2018-07-19 11:48:22 +02:00
/* Return a list of all tags associated with the cluster specific cluster within the galaxy ( or all clusters if $clusterValue is false )
* The counts are restricted to the event IDs that the user is allowed to see .
*/
public function getTags ( $galaxyType , $clusterValue = false , $user )
{
$this -> Event = ClassRegistry :: init ( 'Event' );
$event_ids = $this -> Event -> fetchEventIds ( $user , false , false , false , true );
$tags = $this -> Event -> EventTag -> Tag -> find ( 'list' , array (
'conditions' => array ( 'name LIKE' => 'misp-galaxy:' . $galaxyType . '="' . ( $clusterValue ? $clusterValue : '%' ) . '"' ),
'fields' => array ( 'name' , 'id' ),
));
$this -> Event -> EventTag -> virtualFields [ 'tag_count' ] = 'COUNT(id)' ;
$tagCounts = $this -> Event -> EventTag -> find ( 'list' , array (
'conditions' => array ( 'EventTag.tag_id' => array_values ( $tags ), 'EventTag.event_id' => $event_ids ),
'fields' => array ( 'EventTag.tag_id' , 'EventTag.tag_count' ),
'group' => array ( 'EventTag.tag_id' )
));
foreach ( $tags as $k => $v ) {
if ( isset ( $tagCounts [ $v ])) {
$tags [ $k ] = array ( 'count' => $tagCounts [ $v ], 'tag_id' => $v );
} else {
unset ( $tags [ $k ]);
}
}
return $tags ;
}
2016-12-09 07:58:03 +01:00
2018-07-19 11:48:22 +02:00
/* Fetch a cluster along with all elements and the galaxy it belongs to
* - In the future , once we move to galaxy 2.0 , pass a user along for access control
* - maybe in the future remove the galaxy itself once we have logos with each galaxy
*/
public function getCluster ( $name )
{
2018-11-23 14:11:33 +01:00
if ( isset ( $this -> __clusterCache [ $name ])) {
return $this -> __clusterCache [ $name ];
}
2019-10-18 16:13:26 +02:00
if ( is_numeric ( $name )) {
$conditions = array ( 'GalaxyCluster.id' => $name );
} else {
$conditions = array ( 'LOWER(GalaxyCluster.tag_name)' => strtolower ( $name ));
}
2018-07-19 11:48:22 +02:00
$cluster = $this -> find ( 'first' , array (
'conditions' => $conditions ,
'contain' => array ( 'Galaxy' , 'GalaxyElement' )
));
2019-10-18 16:13:26 +02:00
2018-07-19 11:48:22 +02:00
if ( ! empty ( $cluster )) {
2019-10-18 16:13:26 +02:00
$cluster = $this -> postprocess ( $cluster );
}
$this -> __clusterCache [ $name ] = $cluster ;
return $cluster ;
}
/**
* @ param array $events
* @ param bool $replace
* @ return array
*/
public function attachClustersToEventIndex ( array $events , $replace = false )
{
$clusterTagNames = array ();
foreach ( $events as $event ) {
foreach ( $event [ 'EventTag' ] as $k2 => $eventTag ) {
if ( substr ( $eventTag [ 'Tag' ][ 'name' ], 0 , strlen ( 'misp-galaxy:' )) === 'misp-galaxy:' ) {
$clusterTagNames [] = strtolower ( $eventTag [ 'Tag' ][ 'name' ]);
}
2018-07-19 11:48:22 +02:00
}
2019-10-18 16:13:26 +02:00
}
2020-09-01 17:56:32 +02:00
if ( empty ( $clusterTagNames )) {
return $events ;
}
2019-10-18 16:13:26 +02:00
$clusters = $this -> find ( 'all' , array (
'conditions' => array ( 'LOWER(GalaxyCluster.tag_name)' => $clusterTagNames ),
'contain' => array ( 'Galaxy' , 'GalaxyElement' ),
));
$clustersByTagName = array ();
foreach ( $clusters as $cluster ) {
$clustersByTagName [ strtolower ( $cluster [ 'GalaxyCluster' ][ 'tag_name' ])] = $cluster ;
}
foreach ( $events as $k => $event ) {
foreach ( $event [ 'EventTag' ] as $k2 => $eventTag ) {
$tagName = strtolower ( $eventTag [ 'Tag' ][ 'name' ]);
if ( isset ( $clustersByTagName [ $tagName ])) {
$cluster = $this -> postprocess ( $clustersByTagName [ $tagName ], $eventTag [ 'Tag' ][ 'id' ]);
$cluster [ 'GalaxyCluster' ][ 'tag_id' ] = $eventTag [ 'Tag' ][ 'id' ];
$cluster [ 'GalaxyCluster' ][ 'local' ] = $eventTag [ 'local' ];
$events [ $k ][ 'GalaxyCluster' ][] = $cluster [ 'GalaxyCluster' ];
if ( $replace ) {
unset ( $events [ $k ][ 'EventTag' ][ $k2 ]);
}
2018-07-19 11:48:22 +02:00
}
}
2019-10-18 16:13:26 +02:00
}
return $events ;
}
/**
* @ param array $cluster
* @ param int | null $tagId
* @ return array
*/
private function postprocess ( array $cluster , $tagId = null )
{
if ( isset ( $cluster [ 'Galaxy' ])) {
$cluster [ 'GalaxyCluster' ][ 'Galaxy' ] = $cluster [ 'Galaxy' ];
unset ( $cluster [ 'Galaxy' ]);
}
$elements = array ();
foreach ( $cluster [ 'GalaxyElement' ] as $element ) {
if ( ! isset ( $elements [ $element [ 'key' ]])) {
$elements [ $element [ 'key' ]] = array ( $element [ 'value' ]);
} else {
$elements [ $element [ 'key' ]][] = $element [ 'value' ];
}
}
unset ( $cluster [ 'GalaxyElement' ]);
$cluster [ 'GalaxyCluster' ][ 'meta' ] = $elements ;
if ( $tagId ) {
$cluster [ 'GalaxyCluster' ][ 'tag_id' ] = $tagId ;
} else {
2018-07-19 11:48:22 +02:00
$this -> Tag = ClassRegistry :: init ( 'Tag' );
$tag_id = $this -> Tag -> find (
'first' ,
array (
'conditions' => array (
2019-08-02 16:28:08 +02:00
'LOWER(Tag.name)' => strtolower ( $cluster [ 'GalaxyCluster' ][ 'tag_name' ])
2018-07-19 11:48:22 +02:00
),
'recursive' => - 1 ,
'fields' => array ( 'Tag.id' )
)
);
if ( ! empty ( $tag_id )) {
$cluster [ 'GalaxyCluster' ][ 'tag_id' ] = $tag_id [ 'Tag' ][ 'id' ];
}
}
2016-12-09 07:58:03 +01:00
2019-10-18 16:13:26 +02:00
return $cluster ;
2018-07-19 11:48:22 +02:00
}
2019-11-06 10:38:34 +01:00
public function getClusterTagsFromMeta ( $galaxyElements )
{
// AND operator between cluster metas
$tmpResults = array ();
foreach ( $galaxyElements as $galaxyElementKey => $galaxyElementValue ) {
$tmpResults [] = array_values ( $this -> GalaxyElement -> find ( 'list' , array (
'conditions' => array (
'key' => $galaxyElementKey ,
'value' => $galaxyElementValue ,
),
'fields' => array ( 'galaxy_cluster_id' ),
'recursive' => - 1
)));
}
$clusterTags = array ();
if ( ! empty ( $tmpResults )) {
// Get all Clusters matching all conditions
$matchingClusters = $tmpResults [ 0 ];
array_shift ( $tmpResults );
foreach ( $tmpResults as $tmpResult ) {
$matchingClusters = array_intersect ( $matchingClusters , $tmpResult );
}
2020-09-15 23:52:52 +02:00
2019-11-06 10:38:34 +01:00
$clusterTags = $this -> find ( 'list' , array (
'conditions' => array ( 'id' => $matchingClusters ),
'fields' => array ( 'GalaxyCluster.tag_name' ),
'recursive' => - 1
));
}
return array_values ( $clusterTags );
}
2020-09-15 23:52:52 +02:00
public function getTagIdByClusterId ( $cluster_id )
{
$cluster = $this -> find ( 'first' , [
'recursive' => - 1 ,
'conditions' => [ 'GalaxyCluster.id' => $cluster_id ],
'contain' => [ 'Tag' ]
]);
return empty ( $cluster [ 'Tag' ][ 'id' ]) ? false : $cluster [ 'Tag' ][ 'id' ];
}
2016-12-05 00:47:34 +01:00
}