Merge branch '2.4' of github.com:MISP/MISP into 2.4

pull/3995/head
chrisr3d 2019-01-07 09:14:01 +01:00
commit 755935d294
35 changed files with 1473 additions and 234 deletions

View File

@ -904,7 +904,7 @@ CREATE TABLE IF NOT EXISTS `tags` (
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`colour` varchar(7) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`exportable` tinyint(1) NOT NULL,
`org_id` tinyint(1) NOT NULL DEFAULT 0,
`org_id` int(11) NOT NULL DEFAULT 0,
`user_id` int(11) NOT NULL DEFAULT 0,
`hide_tag` tinyint(1) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),

View File

@ -46,7 +46,7 @@ class AppController extends Controller
public $helpers = array('Utility', 'OrgImg');
private $__queryVersion = '50';
private $__queryVersion = '51';
public $pyMispVersion = '2.4.99';
public $phpmin = '5.6.5';
public $phprec = '7.0.16';

View File

@ -2838,15 +2838,31 @@ class AttributesController extends AppController
$tag_id = $this->request->data['tag'];
}
if (!is_numeric($tag_id)) {
$tag = $this->Attribute->AttributeTag->Tag->find('first', array('recursive' => -1, 'conditions' => array('LOWER(Tag.name) LIKE' => strtolower(trim($tag_id)))));
if (empty($tag)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag.')), 'status' => 200, 'type' => 'json'));
if (preg_match('/^collection_[0-9]+$/i', $tag_id)) {
$tagChoice = explode('_', $tag_id)[1];
$this->loadModel('TagCollection');
$tagCollection = $this->TagCollection->fetchTagCollection($this->Auth->user(), array('conditions' => array('TagCollection.id' => $tagChoice)));
if (empty($tagCollection)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag Collection.')), 'status'=>200, 'type' => 'json'));
}
$tag_id_list = array();
foreach ($tagCollection[0]['TagCollectionTag'] as $tagCollectionTag) {
$tag_id_list[] = $tagCollectionTag['tag_id'];
}
} else {
$tag = $this->Event->EventTag->Tag->find('first', array('recursive' => -1, 'conditions' => $conditions));
if (empty($tag)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag.')), 'status'=>200, 'type' => 'json'));
}
$tag_id = $tag['Tag']['id'];
}
$tag_id = $tag['Tag']['id'];
}
if (!isset($idList)) {
$idList = array($id);
}
if (empty($tag_id_list)) {
$tag_id_list = array($tag_id);
}
$success = 0;
$fails = 0;
foreach ($idList as $id) {
@ -2874,40 +2890,44 @@ class AttributesController extends AppController
$this->Attribute->Event->insertLock($this->Auth->user(), $eventId);
}
$this->Attribute->recursive = -1;
$this->Attribute->AttributeTag->Tag->id = $tag_id;
if (!$this->Attribute->AttributeTag->Tag->exists()) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag.')), 'status' => 200, 'type' => 'json'));
}
$tag = $this->Attribute->AttributeTag->Tag->find('first', array(
'conditions' => array('Tag.id' => $tag_id),
'recursive' => -1,
'fields' => array('Tag.name')
));
$found = $this->Attribute->AttributeTag->find('first', array(
'conditions' => array(
'attribute_id' => $id,
'tag_id' => $tag_id
),
'recursive' => -1,
));
$this->autoRender = false;
if (!empty($found)) {
$fails++;
continue;
}
$this->Attribute->AttributeTag->create();
if ($this->Attribute->AttributeTag->save(array('attribute_id' => $id, 'tag_id' => $tag_id, 'event_id' => $eventId))) {
$event['Event']['published'] = 0;
$date = new DateTime();
$event['Event']['timestamp'] = $date->getTimestamp();
$this->Attribute->Event->save($event);
$this->Attribute->data['Attribute']['timestamp'] = $date->getTimestamp();
$this->Attribute->save($this->Attribute->data);
$log = ClassRegistry::init('Log');
$log->createLogEntry($this->Auth->user(), 'tag', 'Attribute', $id, 'Attached tag (' . $tag_id . ') "' . $tag['Tag']['name'] . '" to attribute (' . $id . ')', 'Attribute (' . $id . ') tagged as Tag (' . $tag_id . ')');
$success++;
} else {
$fails++;
foreach ($tag_id_list as $tag_id) {
$this->Attribute->AttributeTag->Tag->id = $tag_id;
if (!$this->Attribute->AttributeTag->Tag->exists()) {
$fails++;
continue;
}
$tag = $this->Attribute->AttributeTag->Tag->find('first', array(
'conditions' => array('Tag.id' => $tag_id),
'recursive' => -1,
'fields' => array('Tag.name')
));
$found = $this->Attribute->AttributeTag->find('first', array(
'conditions' => array(
'attribute_id' => $id,
'tag_id' => $tag_id
),
'recursive' => -1,
));
$this->autoRender = false;
if (!empty($found)) {
$fails++;
continue;
}
$this->Attribute->AttributeTag->create();
if ($this->Attribute->AttributeTag->save(array('attribute_id' => $id, 'tag_id' => $tag_id, 'event_id' => $eventId))) {
$event['Event']['published'] = 0;
$date = new DateTime();
$event['Event']['timestamp'] = $date->getTimestamp();
$this->Attribute->Event->save($event);
$this->Attribute->data['Attribute']['timestamp'] = $date->getTimestamp();
$this->Attribute->save($this->Attribute->data);
$log = ClassRegistry::init('Log');
$log->createLogEntry($this->Auth->user(), 'tag', 'Attribute', $id, 'Attached tag (' . $tag_id . ') "' . $tag['Tag']['name'] . '" to attribute (' . $id . ')', 'Attribute (' . $id . ') tagged as Tag (' . $tag_id . ')');
$success++;
} else {
$fails++;
}
}
}
if ($fails == 0) {

View File

@ -181,6 +181,7 @@ class ACLComponent extends Component
'selectGalaxy' => array('perm_tagger'),
'selectGalaxyNamespace' => array('perm_tagger'),
'selectCluster' => array('perm_tagger'),
'showGalaxies' => array('*'),
'update' => array(),
'view' => array('*'),
'viewGraph' => array('*')
@ -382,6 +383,16 @@ class ACLComponent extends Component
'viewSightings' => array('perm_sighting'),
'quickAdd' => array('perm_sighting')
),
'tagCollections' => array(
'add' => array('perm_tag_editor'),
'addTag' => array('perm_tag_editor'),
'delete' => array('perm_tag_editor'),
'edit' => array('perm_tag_editor'),
'getRow' => array('perm_tag_editor'),
'index' => array('*'),
'removeTag' => array('perm_tag_editor'),
'view' => array('*')
),
'tags' => array(
'add' => array('perm_tag_editor'),
'attachTagToObject' => array('perm_tagger'),
@ -394,6 +405,7 @@ class ACLComponent extends Component
'selectTaxonomy' => array('perm_tagger'),
'showEventTag' => array('*'),
'showAttributeTag' => array('*'),
'showTagControllerTag' => array('*'),
'tagStatistics' => array('*'),
'view' => array('*'),
'viewGraph' => array('*'),

View File

@ -1848,7 +1848,7 @@ class EventsController extends AppController
$this->Event->read(null, $target_id);
// check if private and user not authorised to edit
if (!$this->_isSiteAdmin() && ($this->Event->data['Event']['orgc_id'] != $this->_checkOrg() || !($this->userRole['perm_modify']))) {
$this->Flash->error(__('You are not authorised to do that. Please consider using the \'propose attribute\' feature.'));
$this->Flash->error(__("You are not authorised to do that. Please consider using the 'propose attribute' feature."));
$this->redirect(array('action' => 'view', $target_id));
}
$this->Event->insertLock($this->Auth->user(), $target_id);
@ -3318,11 +3318,24 @@ class EventsController extends AppController
$conditions['Tag.user_id'] = array('0', $this->Auth->user('id'));
}
if (!is_numeric($tag_id)) {
$tag = $this->Event->EventTag->Tag->find('first', array('recursive' => -1, 'conditions' => $conditions));
if (empty($tag)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag.')), 'status'=>200, 'type' => 'json'));
if (preg_match('/^collection_[0-9]+$/i', $tag_id)) {
$tagChoice = explode('_', $tag_id)[1];
$this->loadModel('TagCollection');
$tagCollection = $this->TagCollection->fetchTagCollection($this->Auth->user(), array('conditions' => array('TagCollection.id' => $tagChoice)));
if (empty($tagCollection)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag Collection.')), 'status'=>200, 'type' => 'json'));
}
$tag_id_list = array();
foreach ($tagCollection[0]['TagCollectionTag'] as $tagCollectionTag) {
$tag_id_list[] = $tagCollectionTag['tag_id'];
}
} else {
$tag = $this->Event->EventTag->Tag->find('first', array('recursive' => -1, 'conditions' => $conditions));
if (empty($tag)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag.')), 'status'=>200, 'type' => 'json'));
}
$tag_id = $tag['Tag']['id'];
}
$tag_id = $tag['Tag']['id'];
}
$this->Event->recursive = -1;
$event = $this->Event->read(array(), $id);
@ -3334,37 +3347,53 @@ class EventsController extends AppController
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'You don\'t have permission to do that.')), 'status'=>200, 'type' => 'json'));
}
}
$this->Event->EventTag->Tag->id = $tag_id;
if (!$this->Event->EventTag->Tag->exists()) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag.')), 'status'=>200, 'type' => 'json'));
}
$tag = $this->Event->EventTag->Tag->find('first', array(
'conditions' => array('Tag.id' => $tag_id),
'recursive' => -1,
'fields' => array('Tag.name')
));
$found = $this->Event->EventTag->find('first', array(
'conditions' => array(
'event_id' => $id,
'tag_id' => $tag_id
),
'recursive' => -1,
));
$this->autoRender = false;
if (!empty($found)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Tag is already attached to this event.')), 'status'=>200, 'type' => 'json'));
$error = false;
$success = false;
if (empty($tag_id_list)) {
$tag_id_list = array($tag_id);
}
$this->Event->EventTag->create();
if ($this->Event->EventTag->save(array('event_id' => $id, 'tag_id' => $tag_id))) {
$event['Event']['published'] = 0;
$date = new DateTime();
$event['Event']['timestamp'] = $date->getTimestamp();
$this->Event->save($event);
$log = ClassRegistry::init('Log');
$log->createLogEntry($this->Auth->user(), 'tag', 'Event', $id, 'Attached tag (' . $tag_id . ') "' . $tag['Tag']['name'] . '" to event (' . $id . ')', 'Event (' . $id . ') tagged as Tag (' . $tag_id . ')');
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => 'Tag added.', 'check_publish' => true)), 'status'=>200, 'type' => 'json'));
foreach ($tag_id_list as $tag_id) {
$this->Event->EventTag->Tag->id = $tag_id;
if (!$this->Event->EventTag->Tag->exists()) {
$error = __('Invalid Tag.');
continue;
}
$tag = $this->Event->EventTag->Tag->find('first', array(
'conditions' => array('Tag.id' => $tag_id),
'recursive' => -1,
'fields' => array('Tag.name')
));
$found = $this->Event->EventTag->find('first', array(
'conditions' => array(
'event_id' => $id,
'tag_id' => $tag_id
),
'recursive' => -1,
));
if (!empty($found)) {
$error = __('Tag is already attached to this event.');
continue;
}
$this->Event->EventTag->create();
if ($this->Event->EventTag->save(array('event_id' => $id, 'tag_id' => $tag_id))) {
$event['Event']['published'] = 0;
$date = new DateTime();
$event['Event']['timestamp'] = $date->getTimestamp();
$this->Event->save($event);
$log = ClassRegistry::init('Log');
$log->createLogEntry($this->Auth->user(), 'tag', 'Event', $id, 'Attached tag (' . $tag_id . ') "' . $tag['Tag']['name'] . '" to event (' . $id . ')', 'Event (' . $id . ') tagged as Tag (' . $tag_id . ')');
$success = __('Tag(s) added.');
} else {
$fail = __('Tag could not be added.');
}
}
if ($success) {
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => __('Tag(s) added.'), 'check_publish' => true)), 'status'=>200, 'type' => 'json'));
} elseif (empty($fail)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => __('All tags are already present, nothing to add.'), 'check_publish' => true)), 'status'=>200, 'type' => 'json'));
} else {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Tag could not be added.')), 'status'=>200, 'type' => 'json'));
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => $fail)), 'status'=>200, 'type' => 'json'));
}
}

View File

@ -173,8 +173,7 @@ class GalaxiesController extends AppController
{
$cluster_id = $this->request->data['Galaxy']['target_id'];
$result = $this->Galaxy->attachCluster($this->Auth->user(), $target_type, $target_id, $cluster_id);
$this->Flash->info($result);
$this->redirect($this->referer());
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => $result, 'check_publish' => true)), 'status'=>200, 'type' => 'json'));
}
public function attachMultipleClusters($target_id, $target_type = 'event')
@ -204,4 +203,28 @@ class GalaxiesController extends AppController
$this->set('galaxy_id', $cluster['Galaxy']['id']);
$this->render('/Events/view_graph');
}
public function showGalaxies($id, $scope = 'event')
{
$this->layout = 'ajax';
$this->set('scope', $scope);
if ($scope == 'event') {
$this->loadModel('Event');
$object = $this->Event->fetchEvent($this->Auth->user(), array('eventid' => $id, 'metadata' => 1));
if (empty($object)) {
throw new MethodNotAllowedException('Invalid event.');
}
$this->set('object', $object[0]);
} elseif ($scope == 'attribute') {
$this->loadModel('Attribute');
$object = $this->Attribute->fetchAttributes($this->Auth->user(), array('conditions' => array('Attribute.id' => $id)));
if (empty($object)) {
throw new MethodNotAllowedException('Invalid attribute.');
}
$object[0] = $this->Attribute->Event->massageTags($object[0], 'Attribute');
}
$this->set('object', $object[0]);
$this->render('/Events/ajax/ajaxGalaxies');
}
}

View File

@ -821,6 +821,11 @@ class ServersController extends AppController
return $this->Server->loadAvailableLanguages();
}
private function __loadTagCollections()
{
return $this->Server->loadTagCollections($this->Auth->user());
}
private function __loadLocalOrgs()
{
$this->loadModel('Organisation');

View File

@ -0,0 +1,343 @@
<?php
App::uses('AppController', 'Controller');
class TagCollectionsController extends AppController
{
public $components = array(
'Security',
'AdminCrud',
'RequestHandler'
);
public $paginate = array(
'limit' => 60,
'order' => array(
'TagCollection.name' => 'ASC'
),
'recursive' => -1,
'contain' => array('TagCollectionTag' => array('Tag'), 'User', 'Organisation')
);
public function add()
{
if ($this->request->is('post')) {
$this->TagCollection->create();
if (!isset($this->request->data['TagCollection'])) {
$this->request->data = array('TagCollection' => $this->request->data);
}
$this->request->data['TagCollection']['org_id'] = $this->Auth->user('org_id');
$this->request->data['TagCollection']['user_id'] = $this->Auth->user('id');
if ($this->TagCollection->save($this->request->data)) {
if ($this->_isRest()) {
$tagCollection = $this->TagCollection->find('first', array(
'recursive' => -1,
'conditions' => array('TagCollection.id' => $this->TagCollection->id)
));
return $this->RestResponse->viewData($tagCollection, $this->response->type());
} else {
$this->Flash->success(__('The tag collection has been saved'));
$this->redirect(array('action' => 'index'));
}
} else {
$message = json_encode($this->TagCollection->validationErrors);
if ($this->_isRest()) {
return $this->RestResponse->saveFailResponse('TagCollection', 'add', false, $message, $this->response->type());
} else {
$this->Flash->error(__('The tag collection could not be added. Reason: ') . $message);
}
}
} elseif ($this->_isRest()) {
return $this->RestResponse->describe('TagCollection', 'add', false, $this->response->type());
}
$this->set('action', 'add');
}
public function view()
{
}
public function edit($id)
{
$this->TagCollection->id = $id;
if (!$this->TagCollection->exists()) {
throw new NotFoundException(__('Invalid Tag Collection'));
}
$tagCollection = $this->TagCollection->find('first', array(
'conditions' => array('TagCollection.id' => $id),
'recursive' => -1
));
if (!$this->_isSiteAdmin() && $tagCollection['TagCollection']['org_id'] !== $this->Auth->user('org_id')) {
throw new MethodNotAllowedException(__('You don\'t have editing rights on this Tag Collection.'));
}
if ($this->request->is('post') || $this->request->is('put')) {
if (!isset($this->request->data['TagCollection'])) {
$this->request->data = array('TagCollection' => $this->request->data);
}
$this->request->data['TagCollection']['id'] = $tagCollection['TagCollection']['id'];
$this->request->data['TagCollection']['uuid'] = $tagCollection['TagCollection']['uuid'];
if ($this->TagCollection->save($this->request->data)) {
if ($this->_isRest()) {
$tagCollection = $this->TagCollection->find('first', array(
'recursive' => -1,
'conditions' => array('TagCollection.id' => $this->TagCollection->id)
));
return $this->RestResponse->viewData($tagCollection, $this->response->type());
} else {
$this->Flash->success(__('The tag collection has been saved'));
$this->redirect(array('action' => 'index'));
}
} else {
$message = json_encode($this->TagCollection->validationErrors);
if ($this->_isRest()) {
return $this->RestResponse->saveFailResponse('TagCollection', 'add', false, $message, $this->response->type());
} else {
$this->Flash->error(__('The tag collection could not be added. Reason: ') . $message);
}
}
} elseif ($this->_isRest()) {
return $this->RestResponse->describe('TagCollection', 'add', false, $this->response->type());
} else {
$this->request->data = $tagCollection;
}
$this->set('action', 'edit');
$this->render('add');
}
public function delete($id)
{
$tagCollection = $this->TagCollection->fetchTagCollection($this->Auth->user(), array('conditions' => array('TagCollection.id' => $id)));
if (empty($tagCollection)) {
throw new NotFoundException(__('Invalid tag collection.'));
}
$tagCollection = $tagCollection[0];
if ($this->TagCollection->checkAccess($this->Auth->user(), $tagCollection, 'write')) {
$result = $this->TagCollection->delete($id);
if ($result) {
$message = __('Tag collection deleted.');
if ($this->_isRest()) {
return $this->RestResponse->saveSuccessResponse('TagCollections', 'delete', false, $this->response->type(), $message);
} else {
$this->Flash->success($message);
$this->redirect('index');
}
} else {
$message = __('Tag collection could not be deleted.');
if ($this->_isRest()) {
return $this->RestResponse->saveFailResponse('TagCollections', 'delete', false, $message, $this->response->type());
} else {
$this->Flash->error($message);
$this->redirect('index');
}
}
} else {
throw new NotFoundException(__('You are not allowed to delete that.'));
}
}
public function addTag($id = false, $tag_id = false)
{
if (!$this->request->is('post')) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'You don\'t have permission to do that.')), 'status'=>200, 'type' => 'json'));
}
$rearrangeRules = array(
'request' => false,
'TagCollection' => false,
'tag_id' => 'tag',
'tag_collection_id' => 'tag_collection',
'id' => 'tag_collection'
);
$RearrangeTool = new RequestRearrangeTool();
$this->request->data = $RearrangeTool->rearrangeArray($this->request->data, $rearrangeRules);
if ($id === false) {
$id = $this->request->data['tag_collection'];
}
if ($tag_id === false) {
$tag_id = $this->request->data['tag'];
}
$conditions = array('LOWER(Tag.name) LIKE' => strtolower(trim($tag_id)));
if (!$this->_isSiteAdmin()) {
$conditions['Tag.org_id'] = array('0', $this->Auth->user('org_id'));
$conditions['Tag.user_id'] = array('0', $this->Auth->user('id'));
}
if (!is_numeric($tag_id)) {
$tag = $this->TagCollection->Tag->find('first', array('recursive' => -1, 'conditions' => $conditions));
if (empty($tag)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag.')), 'status'=>200, 'type' => 'json'));
}
$tag_id = $tag['Tag']['id'];
}
$tagCollection = $this->TagCollection->find('first', array(
'recursive' => -1,
'conditions' => array('TagCollection.id' => $id)
));
if (empty($tagCollection)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid tag collection.')), 'status'=>200, 'type' => 'json'));
}
if (!$this->_isSiteAdmin()) {
if (!$this->userRole['perm_tagger'] || ($this->Auth->user('org_id') !== $tag_collection['TagCollection']['org_id'])) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'You don\'t have permission to do that.')), 'status'=>200, 'type' => 'json'));
}
}
$this->TagCollection->TagCollectionTag->Tag->id = $tag_id;
if (!$this->TagCollection->TagCollectionTag->Tag->exists()) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Invalid Tag.')), 'status'=>200, 'type' => 'json'));
}
$tag = $this->TagCollection->TagCollectionTag->Tag->find('first', array(
'conditions' => array('Tag.id' => $tag_id),
'recursive' => -1,
'fields' => array('Tag.name')
));
$found = $this->TagCollection->TagCollectionTag->find('first', array(
'conditions' => array(
'tag_collection_id' => $id,
'tag_id' => $tag_id
),
'recursive' => -1,
));
$this->autoRender = false;
if (!empty($found)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Tag is already attached to this collection.')), 'status'=>200, 'type' => 'json'));
}
$this->TagCollection->TagCollectionTag->create();
if ($this->TagCollection->TagCollectionTag->save(array('tag_collection_id' => $id, 'tag_id' => $tag_id))) {
$log = ClassRegistry::init('Log');
$log->createLogEntry($this->Auth->user(), 'tag', 'TagCollection', $id, 'Attached tag (' . $tag_id . ') "' . $tag['Tag']['name'] . '" to collection (' . $id . ')', 'Event (' . $id . ') tagged as Tag (' . $tag_id . ')');
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => 'Tag added.')), 'status'=>200, 'type' => 'json'));
} else {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => 'Tag could not be added.')), 'status'=>200, 'type' => 'json'));
}
}
public function removeTag($id = false, $tag_id = false)
{
if (!$this->request->is('post')) {
$this->set('id', $id);
$this->set('tag_id', $tag_id);
$this->set('model', 'tag_collection');
$this->layout = 'ajax';
$this->render('/Attributes/ajax/tagRemoveConfirmation');
} else {
$rearrangeRules = array(
'request' => false,
'TagCollection' => false,
'tag_id' => 'tag',
'tag_collection_id' => 'tag_collection',
'id' => 'tag_collection'
);
$RearrangeTool = new RequestRearrangeTool();
$this->request->data = $RearrangeTool->rearrangeArray($this->request->data, $rearrangeRules);
if ($id === false) {
$id = $this->request->data['tag_collection'];
}
if ($tag_id === false) {
$tag_id = $this->request->data['tag'];
}
$tagCollection = $this->TagCollection->find('first', array(
'recursive' => -1,
'conditions' => array(
'TagCollection.id' => $id
),
'contain' => array(
'TagCollectionTag' => array(
'Tag'
)
)
));
if (empty($tagCollection)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => __('Invalid tag collection.'))), 'status' => 200, 'type' => 'json'));
}
$found = false;
if (!$this->_isSiteAdmin() && $this->Auth->user('org_id') !== $tagCollection['TagCollection']['org_id']) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => __('Insufficient privileges to remove the tag from the collection.'))), 'status' => 200, 'type' => 'json'));
}
foreach ($tagCollection['TagCollectionTag'] as $TagCollectionTag) {
if ((is_numeric($tag_id) && $TagCollectionTag['Tag']['id'] == $tag_id) || $TagCollectionTag['Tag']['name'] === $tag_id) {
$found = true;
$tag = $TagCollectionTag;
$result = $this->TagCollection->TagCollectionTag->delete($TagCollectionTag['id']);
break;
}
}
if (!$found) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => __('Invalid tag or tag not associated with the collection.'))), 'status' => 200, 'type' => 'json'));
}
if (!$result) {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => __('Failed to remove tag from the collection.'))), 'status' => 200, 'type' => 'json'));
}
$log = ClassRegistry::init('Log');
$log->createLogEntry($this->Auth->user(), 'tag', 'TagCollection', $id, 'Removed tag (' . $tag['Tag']['id'] . ') "' . $tag['Tag']['name'] . '" from tag collection (' . $id . ')', 'Tag collection (' . $id . ') - untagged Tag (' . $tag_id . ')');
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => 'Tag removed.')), 'status' => 200));
}
}
public function index()
{
//$this->Auth->user('Role')['perm_site_admin']);
$conditions = array();
if (!$this->_isSiteAdmin()) {
$conditions = array(
'OR' => array(
'TagCollection.all_orgs' => 1,
'TagCollection.org_id' => $this->Auth->user('org_id')
)
);
$this->paginate['conditions'] = $conditions;
}
if ($this->_isRest()) {
$params = array(
'recursive' => -1,
'contain' => array('TagCollectionTag' => array('Tag'), 'Organisation', 'User')
);
if (!empty($conditions)) {
$params['conditions'] = $conditions;
}
$namedParams = array('limit', 'page');
foreach ($namedParams as $namedParam) {
if (!empty($this->params['named'][$namedParam])) {
$params['limit'] = $this->params['named'][$namedParam];
}
}
$list = $this->TagCollection->find('all', $params);
} else {
$list = $this->paginate();
}
$this->loadModel('Event');
foreach ($list as $k => $tag_collection) {
$list[$k] = $this->TagCollection->cullBlockedTags($this->Auth->user(), $tag_collection);
$list[$k] = $this->Event->massageTags($list[$k], 'TagCollection', false, true);
if (!$this->_isSiteAdmin() && $list[$k]['TagCollection']['org_id'] !== $this->Auth->user('org_id')) {
unset($list[$k]['User']);
unset($list[$k]['TagCollection']['user_id']);
}
}
if ($this->_isRest()) {
return $this->RestResponse->viewData($list, $this->response->type());
} else {
$this->set('list', $list);
}
}
public function getRow($id)
{
$params = array(
'recursive' => -1,
'contain' => array('TagCollectionTag' => array('Tag'), 'User', 'Organisation'),
'conditions' => array('TagCollection.id' => $id)
);
$item = $this->TagCollection->find('first', $params);
if (empty($item)) {
throw new NotFoundException('Invalid tag collection.');
}
if (!$this->_isSiteAdmin() && $item['TagCollection']['org_id'] !== $this->Auth->user('org_id')) {
unset($item['User']);
unset($item['TagCollection']['user_id']);
}
$this->loadModel('Event');
$item = $this->Event->massageTags($item, 'TagCollection', false, true);
$this->layout = false;
$this->set('item', $item);
}
}

View File

@ -519,6 +519,39 @@ class TagsController extends AppController
$this->render('/Attributes/ajax/ajaxAttributeTags');
}
public function showTagControllerTag($id)
{
$this->loadModel('TagCollection');
$tagCollection = $this->TagCollection->find('first', array(
'recursive' => -1,
'contain' => array('TagCollection'),
'conditions' => array('TagCollection.id' => $id)
));
if (empty($tagCollection) || (!$this->_isSiteAdmin() && $tagCollection['org_id'] !== $this->Auth->user('org_id'))) {
throw new MethodNotAllowedException('Invalid tag_collection.');
}
$this->loadModel('GalaxyCluster');
$cluster_names = $this->GalaxyCluster->find('list', array('fields' => array('GalaxyCluster.tag_name'), 'group' => array('GalaxyCluster.id', 'GalaxyCluster.tag_name')));
$this->helpers[] = 'TextColour';
$tags = $this->TagCollection->TagCollectionTag->find('all', array(
'conditions' => array(
'tag_collection_id' => $id,
'Tag.name !=' => $cluster_names
),
'contain' => array('Tag'),
'fields' => array('Tag.id', 'Tag.colour', 'Tag.name'),
));
$this->set('tags', $tags);
$event = $this->Tag->EventTag->Event->find('first', array(
'recursive' => -1,
'fields' => array('Event.id', 'Event.orgc_id', 'Event.org_id', 'Event.user_id'),
'conditions' => array('Event.id' => $id)
));
$this->set('event', $event);
$this->layout = 'ajax';
$this->render('/Events/ajax/ajaxTags');
}
public function viewTag($id)
{
$tag = $this->Tag->find('first', array(
@ -534,7 +567,7 @@ class TagsController extends AppController
}
public function selectTaxonomy($id, $attributeTag = false)
public function selectTaxonomy($id, $scope = 'event')
{
if (!$this->_isSiteAdmin() && !$this->userRole['perm_tagger']) {
throw new NotFoundException('You don\'t have permission to do that.');
@ -548,96 +581,126 @@ class TagsController extends AppController
unset($options[$k]);
}
}
if ($attributeTag !== false) {
$this->set('attributeTag', true);
}
$this->set('scope', $scope);
$this->set('object_id', $id);
$this->set('options', $options);
$this->set('favourites', $favourites);
$this->render('ajax/taxonomy_choice');
}
public function selectTag($id, $taxonomy_id, $attributeTag = false, $filterData = '')
public function selectTag($id, $taxonomy_id, $scope = 'event', $filterData = '')
{
if (!$this->_isSiteAdmin() && !$this->userRole['perm_tagger']) {
throw new NotFoundException('You don\'t have permission to do that.');
}
$this->loadModel('Taxonomy');
$expanded = array();
if ($taxonomy_id === '0') {
$options = $this->Taxonomy->getAllTaxonomyTags(true);
$expanded = $options;
} elseif ($taxonomy_id === 'favourites') {
$conditions = array('FavouriteTag.user_id' => $this->Auth->user('id'));
$tags = $this->Tag->FavouriteTag->find('all', array(
'conditions' => $conditions,
'recursive' => -1,
'contain' => array('Tag.name')
));
foreach ($tags as $tag) {
$options[$tag['FavouriteTag']['tag_id']] = $tag['Tag']['name'];
$expanded = $options;
}
} elseif ($taxonomy_id === 'all') {
$conditions = array('Tag.org_id' => array(0, $this->Auth->user('org_id')));
$conditions = array('Tag.user_id' => array(0, $this->Auth->user('id')));
$conditions['Tag.hide_tag'] = 0;
$options = $this->Tag->find('list', array('fields' => array('Tag.name'), 'conditions' => $conditions));
$expanded = $options;
} else {
$taxonomies = $this->Taxonomy->getTaxonomy($taxonomy_id);
$options = array();
foreach ($taxonomies['entries'] as $entry) {
if (!empty($entry['existing_tag']['Tag'])) {
$options[$entry['existing_tag']['Tag']['id']] = $entry['existing_tag']['Tag']['name'];
$expanded[$entry['existing_tag']['Tag']['id']] = $entry['expanded'];
}
}
}
// Unset all tags that this user cannot use for tagging, determined by the org restriction on tags
if (!$this->_isSiteAdmin()) {
$banned_tags = $this->Tag->find('list', array(
'conditions' => array(
'NOT' => array(
'Tag.org_id' => array(
0,
$this->Auth->user('org_id')
),
'Tag.user_id' => array(
0,
$this->Auth->user('id')
)
)
),
'fields' => array('Tag.id')
));
foreach ($banned_tags as $banned_tag) {
unset($options[$banned_tag]);
unset($expanded[$banned_tag]);
}
}
$hidden_tags = $this->Tag->find('list', array(
'conditions' => array('Tag.hide_tag' => 1),
$banned_tags = $this->Tag->find('list', array(
'conditions' => array(
'NOT' => array(
'Tag.org_id' => array(
0,
$this->Auth->user('org_id')
),
'Tag.user_id' => array(
0,
$this->Auth->user('id')
)
)
),
'fields' => array('Tag.id')
));
foreach ($hidden_tags as $hidden_tag) {
unset($options[$hidden_tag]);
unset($expanded[$hidden_tag]);
}
if ($attributeTag !== false && $attributeTag !== "false") {
$this->set('attributeTag', true);
}
$this->set('object_id', $id);
foreach ($options as $k => $v) {
if (substr($v, 0, strlen('misp-galaxy:')) === 'misp-galaxy:') {
unset($options[$k]);
$this->set('taxonomy_id', $taxonomy_id);
if ($taxonomy_id === 'collections') {
$this->loadModel('TagCollection');
$tagCollections = $this->TagCollection->fetchTagCollection($this->Auth->user());
$options = array();
$expanded = array();
foreach ($tagCollections as &$tagCollection) {
$options[$tagCollection['TagCollection']['id']] = $tagCollection['TagCollection']['name'];
$expanded[$tagCollection['TagCollection']['id']] = empty($tagCollection['TagCollection']['description']) ? $tagCollection['TagCollection']['name'] : $tagCollection['TagCollection']['description'];
if (!empty($tagCollection['TagCollectionTag'])) {
$tagList = array();
foreach ($tagCollection['TagCollectionTag'] as $k => $tce) {
if (in_array($tce['tag_id'], $banned_tags)) {
unset($tagCollection['TagCollectionTag'][$k]);
} else {
$tagList[] = $tce['Tag']['name'];
}
$tagCollection['TagCollectionTag'] = array_values($tagCollection['TagCollectionTag']);
}
$tagList = implode(', ', $tagList);
$expanded[$tagCollection['TagCollection']['id']] .= sprintf(' (%s)', $tagList);
}
}
$this->set('scope', $scope);
$this->set('object_id', $id);
$this->set('options', $options);
$this->set('expanded', $expanded);
$this->set('custom', $taxonomy_id == 0 ? true : false);
$this->set('filterData', $filterData);
$this->render('ajax/select_tag');
} else {
if ($taxonomy_id === '0') {
$options = $this->Taxonomy->getAllTaxonomyTags(true);
$expanded = $options;
} elseif ($taxonomy_id === 'favourites') {
$conditions = array('FavouriteTag.user_id' => $this->Auth->user('id'));
$tags = $this->Tag->FavouriteTag->find('all', array(
'conditions' => $conditions,
'recursive' => -1,
'contain' => array('Tag.name')
));
foreach ($tags as $tag) {
$options[$tag['FavouriteTag']['tag_id']] = $tag['Tag']['name'];
$expanded = $options;
}
} elseif ($taxonomy_id === 'all') {
$conditions = array('Tag.org_id' => array(0, $this->Auth->user('org_id')));
$conditions = array('Tag.user_id' => array(0, $this->Auth->user('id')));
$conditions['Tag.hide_tag'] = 0;
$options = $this->Tag->find('list', array('fields' => array('Tag.name'), 'conditions' => $conditions));
$expanded = $options;
} else {
$taxonomies = $this->Taxonomy->getTaxonomy($taxonomy_id);
$options = array();
if (!empty($taxonomies['entries'])) {
foreach ($taxonomies['entries'] as $entry) {
if (!empty($entry['existing_tag']['Tag'])) {
$options[$entry['existing_tag']['Tag']['id']] = $entry['existing_tag']['Tag']['name'];
$expanded[$entry['existing_tag']['Tag']['id']] = $entry['expanded'];
}
}
}
}
// Unset all tags that this user cannot use for tagging, determined by the org restriction on tags
if (!$this->_isSiteAdmin()) {
foreach ($banned_tags as $banned_tag) {
unset($options[$banned_tag]);
unset($expanded[$banned_tag]);
}
}
$hidden_tags = $this->Tag->find('list', array(
'conditions' => array('Tag.hide_tag' => 1),
'fields' => array('Tag.id')
));
foreach ($hidden_tags as $hidden_tag) {
unset($options[$hidden_tag]);
unset($expanded[$hidden_tag]);
}
$this->set('scope', $scope);
$this->set('object_id', $id);
foreach ($options as $k => $v) {
if (substr($v, 0, strlen('misp-galaxy:')) === 'misp-galaxy:') {
unset($options[$k]);
}
}
$this->set('options', $options);
$this->set('expanded', $expanded);
$this->set('custom', $taxonomy_id == 0 ? true : false);
$this->set('filterData', $filterData);
$this->render('ajax/select_tag');
}
$this->set('options', $options);
$this->set('expanded', $expanded);
$this->set('custom', $taxonomy_id == 0 ? true : false);
$this->set('filterData', $filterData);
$this->render('ajax/select_tag');
}
public function tagStatistics($percentage = false, $keysort = false)

View File

@ -71,7 +71,8 @@ class AppModel extends Model
1 => false, 2 => false, 3 => false, 4 => true, 5 => false, 6 => false,
7 => false, 8 => false, 9 => false, 10 => false, 11 => false, 12 => false,
13 => false, 14 => false, 15 => false, 18 => false, 19 => false, 20 => false,
21 => false, 22 => false, 23 => false, 24 => false, 25 => false
21 => false, 22 => false, 23 => false, 24 => false, 25 => false, 26 => false,
27 => false
);
public function afterSave($created, $options = array())
@ -1059,6 +1060,32 @@ class AppModel extends Model
$this->__addIndex('galaxy_clusters', 'uuid');
$this->__addIndex('galaxy_clusters', 'collection_uuid');
break;
case 26:
$sqlArray[] = "CREATE TABLE IF NOT EXISTS tag_collections (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uuid` varchar(40) COLLATE utf8_bin DEFAULT NULL,
`user_id` int(11) NOT NULL,
`org_id` int(11) NOT NULL,
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`description` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`all_orgs` tinyint(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
INDEX `uuid` (`uuid`),
INDEX `user_id` (`user_id`),
INDEX `org_id` (`org_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;";
$sqlArray[] = "CREATE TABLE IF NOT EXISTS tag_collection_tags (
`id` int(11) NOT NULL AUTO_INCREMENT,
`tag_collection_id` int(11) NOT NULL,
`tag_id` int(11) NOT NULL,
PRIMARY KEY (id),
INDEX `uuid` (`tag_collection_id`),
INDEX `user_id` (`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;";
break;
case 27:
$sqlArray[] = 'ALTER TABLE `tags` CHANGE `org_id` `org_id` int(11) NOT NULL DEFAULT 0;';
break;
case 'fixNonEmptySharingGroupID':
$sqlArray[] = 'UPDATE `events` SET `sharing_group_id` = 0 WHERE `distribution` != 4;';
$sqlArray[] = 'UPDATE `attributes` SET `sharing_group_id` = 0 WHERE `distribution` != 4;';

View File

@ -3288,6 +3288,39 @@ class Event extends AppModel
}
$this->publish($this->getID(), $passAlong);
}
if (empty($data['Event']['locked']) && !empty(Configure::read('MISP.default_event_tag_collection'))) {
$this->TagCollection = ClassRegistry::init('TagCollection');
$tagCollection = $this->TagCollection->fetchTagCollection($user, array('conditions' => array('TagCollection.id' => Configure::read('MISP.default_event_tag_collection'))));
if (!empty($tagCollection)) {
$tag_id_list = array();
foreach ($tagCollection[0]['TagCollectionTag'] as $tagCollectionTag) {
$tag_id_list[] = $tagCollectionTag['tag_id'];
}
foreach ($tag_id_list as $tag_id) {
$tag = $this->EventTag->Tag->find('first', array(
'conditions' => array('Tag.id' => $tag_id),
'recursive' => -1,
'fields' => array('Tag.name')
));
if (!empty($tag)) {
$found = $this->EventTag->find('first', array(
'conditions' => array(
'event_id' => $this->id,
'tag_id' => $tag_id
),
'recursive' => -1,
));
if (empty($found)) {
$this->EventTag->create();
if ($this->EventTag->save(array('event_id' => $this->id, 'tag_id' => $tag_id))) {
$log = ClassRegistry::init('Log');
$log->createLogEntry($user, 'tag', 'Event', $this->id, 'Attached tag (' . $tag_id . ') "' . $tag['Tag']['name'] . '" to event (' . $this->id . ')', 'Event (' . $this->id . ') tagged as Tag (' . $tag_id . ')');
}
}
}
}
}
}
return true;
} else {
$validationErrors['Event'] = $this->validationErrors;
@ -5244,7 +5277,7 @@ class Event extends AppModel
return $attributes_added;
}
public function massageTags($data, $dataType = 'Event', $excludeGalaxy = false)
public function massageTags($data, $dataType = 'Event', $excludeGalaxy = false, $cullGalaxyTags = false)
{
$data['Galaxy'] = array();
if (empty($this->GalaxyCluster)) {
@ -5277,6 +5310,7 @@ class Event extends AppModel
unset($temp['GalaxyCluster']['Galaxy']);
$data['Galaxy'][count($data['Galaxy']) - 1]['GalaxyCluster'][] = $temp['GalaxyCluster'];
}
unset($data[$dataType . 'Tag'][$k]);
}
}
}

View File

@ -179,55 +179,54 @@ class Galaxy extends AppModel
return true;
}
private function __attachClusterToEvent($user, $target_id, $cluster_id) {
}
public function attachCluster($user, $target_type, $target_id, $cluster_id)
{
$connectorModel = Inflector::camelize($target_type) . 'Tag';
$cluster = $this->GalaxyCluster->find('first', array('recursive' => -1, 'conditions' => array('id' => $cluster_id), 'fields' => array('tag_name', 'id', 'value')));
$this->Tag = ClassRegistry::init('Tag');
if ($target_type == 'event') {
$event = $this->Tag->EventTag->Event->fetchEvent($user, array('eventid' => $target_id, 'metadata' => 1));
if (empty($event)) {
throw new NotFoundException('Invalid event.');
}
$event = $event[0];
$tag_id = $this->Tag->captureTag(array('name' => $cluster['GalaxyCluster']['tag_name'], 'colour' => '#0088cc', 'exportable' => 1), $user);
if ($tag_id === false) {
throw new MethodNotAllowedException('Could not attach cluster.');
}
$this->Tag->EventTag->create();
$existingTag = $this->Tag->EventTag->find('first', array('conditions' => array('event_id' => $target_id, 'tag_id' => $tag_id)));
if (!empty($existingTag)) {
return 'Cluster already attached.';
}
$result = $this->Tag->EventTag->save(array('event_id' => $target_id, 'tag_id' => $tag_id));
} elseif ($target_type == 'attribute') {
$attribute = $this->Tag->AttributeTag->Attribute->fetchAttributes($user, array('conditions' => array('Attribute.id' => $target_id), 'flatten' => 1));
if (empty($attribute)) {
throw new NotFoundException('Invalid attribute.');
}
$attribute = $attribute[0];
$tag_id = $this->Tag->captureTag(array('name' => $cluster['GalaxyCluster']['tag_name'], 'colour' => '#0088cc', 'exportable' => 1), $user);
if ($tag_id === false) {
throw new MethodNotAllowedException('Could not attach cluster.');
}
$this->Tag->AttributeTag->create();
$existingTag = $this->Tag->AttributeTag->find('first', array('conditions' => array('attribute_id' => $target_id, 'tag_id' => $tag_id)));
if (!empty($existingTag)) {
return 'Cluster already attached.';
}
if ($target_type === 'event') {
$target = $this->Tag->EventTag->Event->fetchEvent($user, array('eventid' => $target_id, 'metadata' => 1));
} elseif ($target_type === 'attribute') {
$target = $this->Tag->AttributeTag->Attribute->fetchAttributes($user, array('conditions' => array('Attribute.id' => $target_id), 'flatten' => 1));
} elseif ($target_type === 'tag_collection') {
$target = $this->Tag->TagCollectionTag->TagCollection->fetchTagCollection($user, array('conditions' => array('TagCollection.id' => $target_id)));
}
if (empty($target)) {
throw new NotFoundException(__('Invalid %s.', $target_type));
}
$target = $target[0];
$tag_id = $this->Tag->captureTag(array('name' => $cluster['GalaxyCluster']['tag_name'], 'colour' => '#0088cc', 'exportable' => 1), $user);
$existingTag = $this->Tag->$connectorModel->find('first', array('conditions' => array($target_type . '_id' => $target_id, 'tag_id' => $tag_id)));
if (!empty($existingTag)) {
return 'Cluster already attached.';
}
$this->Tag->$connectorModel->create();
$toSave = array($target_type . '_id' => $target_id, 'tag_id' => $tag_id);
if ($target_type === 'attribute') {
$event = $this->Tag->EventTag->Event->find('first', array(
'conditions' => array(
'Event.id' => $attribute['Attribute']['event_id']
'Event.id' => $target['Attribute']['event_id']
),
'recursive' => -1
));
$result = $this->Tag->AttributeTag->save(array('attribute_id' => $target_id, 'tag_id' => $tag_id, 'event_id' => $attribute['Attribute']['event_id']));
$toSave['event_id'] = $target['Attribute']['event_id'];
}
$result = $this->Tag->$connectorModel->save($toSave);
if ($result) {
$this->Tag->EventTag->Event->insertLock($user, $event['Event']['id']);
$event['Event']['published'] = 0;
$date = new DateTime();
$event['Event']['timestamp'] = $date->getTimestamp();
$this->Tag->EventTag->Event->save($event);
if ($target_type !== 'tag_collection') {
if ($target_type === 'event') {
$event = $target;
}
$this->Tag->EventTag->Event->insertLock($user, $event['Event']['id']);
$event['Event']['published'] = 0;
$date = new DateTime();
$event['Event']['timestamp'] = $date->getTimestamp();
$this->Tag->EventTag->Event->save($event);
}
$this->Log = ClassRegistry::init('Log');
$this->Log->create();
$this->Log->save(array(

View File

@ -522,6 +522,15 @@ class Server extends AppModel
'type' => 'string',
'options' => array('1' => 'High', '2' => 'Medium', '3' => 'Low', '4' => 'undefined'),
),
'default_event_tag_collection' => array(
'level' => 0,
'description' => __('The tag collection to be applied to all events created manually.'),
'value' => 0,
'errorMessage' => '',
'test' => 'testTagCollections',
'type' => 'numeric',
'optionsSource' => 'TagCollections',
),
'tagging' => array(
'level' => 1,
'description' => __('Enable the tagging feature of MISP. This is highly recommended.'),
@ -2643,6 +2652,27 @@ class Server extends AppModel
return true;
}
public function loadTagCollections()
{
$this->TagCollection = ClassRegistry::init('TagCollection');
$user = array('Role' => array('perm_site_admin' => 1));
$tagCollections = $this->TagCollection->fetchTagCollection($user);
$options = array(0 => 'None');
foreach ($tagCollections as $tagCollection) {
$options[intval($tagCollection['TagCollection']['id'])] = $tagCollection['TagCollection']['name'];
}
return $options;
}
public function testTagCollections($value)
{
$tag_collections = $this->loadTagCollections();
if (!isset($tag_collections[intval($value)])) {
return 'Invalid tag_collection.';
}
return true;
}
public function testForNumeric($value)
{
if (!is_numeric($value)) {
@ -3161,6 +3191,23 @@ class Server extends AppModel
public function serverSettingsSaveValue($setting, $value)
{
// validate if current config.php is intact:
$current = file_get_contents(APP . 'Config' . DS . 'config.php');
$current = trim($current);
if (strlen($current) < 20) {
$this->Log = ClassRegistry::init('Log');
$this->Log->create();
$this->Log->save(array(
'org' => 'SYSTEM',
'model' => 'Server',
'model_id' => $id,
'email' => 'SYSTEM',
'action' => 'error',
'user_id' => 0,
'title' => 'Error: Tried to modify server settings but current config is broken.',
));
return false;
}
copy(APP . 'Config' . DS . 'config.php', APP . 'Config' . DS . 'config.php.bk');
$settingObject = $this->getCurrentServerSettings();
foreach ($settingObject as $branchName => $branch) {
@ -3215,6 +3262,17 @@ class Server extends AppModel
// if the saved config file is empty, restore the backup.
if (strlen($config_saved) < 20) {
copy(APP . 'Config' . DS . 'config.php.bk', APP . 'Config' . DS . 'config.php');
$this->Log = ClassRegistry::init('Log');
$this->Log->create();
$this->Log->save(array(
'org' => 'SYSTEM',
'model' => 'Server',
'model_id' => $id,
'email' => 'SYSTEM',
'action' => 'error',
'user_id' => 0,
'title' => 'Error: Something went wrong saving the config file, reverted to backup file.',
));
return false;
}
return true;

View File

@ -52,6 +52,9 @@ class Tag extends AppModel
),
'AttributeTag' => array(
'dependent' => true
),
'TagCollectionTag' => array(
'dependent' => true
)
);

122
app/Model/TagCollection.php Normal file
View File

@ -0,0 +1,122 @@
<?php
App::uses('AppModel', 'Model');
class TagCollection extends AppModel
{
public $useTable = 'tag_collections';
public $displayField = 'name';
public $actsAs = array(
'Trim',
'SysLogLogable.SysLogLogable' => array(
'roleModel' => 'Role',
'roleKey' => 'role_id',
'change' => 'full'
),
'Containable'
);
public $hasMany = array(
'TagCollectionTag' => array(
'dependent' => true
)
);
public $belongsTo = array(
'User',
'Organisation' => array(
'foreignKey' => 'org_id'
)
);
public $whitelistedItems = false;
public $validate = array(
'name' => array(
'valueNotEmpty' => array(
'rule' => array('valueNotEmpty'),
),
'unique' => array(
'rule' => 'isUnique',
'message' => 'A similar name already exists.',
),
)
);
public function beforeValidate($options = array())
{
parent::beforeValidate();
// generate UUID if it doesn't exist
if (empty($this->data['TagCollection']['uuid'])) {
$this->data['TagCollection']['uuid'] = CakeText::uuid();
}
return true;
}
public function fetchTagCollection($user, $params = array())
{
if (empty($user['Role']['perm_site_admin'])) {
$params['conditions']['AND'][] = array(
'OR' => array(
'TagCollection.org_id' => $user['org_id'],
'TagCollection.all_orgs' => 1
)
);
}
if (empty($params['contain'])) {
$params['contain'] = array(
'Organisation',
'User',
'TagCollectionTag' => array('Tag')
);
}
$tagCollections = $this->find('all', $params);
$tagCollections = $this->cullBlockedTags($user, $tagCollections);
return $tagCollections;
}
public function checkAccess($user, $tagCollection, $accessLevel = 'read')
{
if (isset($tagCollection['TagCollection'])) {
$tagCollection = $tagCollection['TagCollection'];
}
if (!empty($user['Role']['admin'])) {
return true;
}
if (!$tagCollection['all_orgs'] && $user['org_id'] != $tagCollection['org_id']) {
return false;
}
if ($accessLevel === 'write') {
if ($tagCollection['org_id'] !== $user['org_id']) {
return false;
}
}
return true;
}
public function cullBlockedTags($user, $tagCollections)
{
$single = false;
if (!isset($tagCollections[0])) {
$tagCollections = array(0 => $tagCollections);
$single = true;
}
if (empty($user['Role']['perm_site_admin'])) {
foreach ($tagCollections as $k => $tagCollection) {
foreach ($tagCollection['TagCollectionTag'] as $k2 => $tagCollectionTag) {
if (
(!empty($tagCollectionTag['Tag']['org_id']) && $tagCollectionTag['Tag']['org_id'] != $user['org_id']) ||
(!empty($tagCollectionTag['Tag']['user_id']) && $tagCollectionTag['Tag']['user_id'] != $user['id']) ||
$tagCollectionTag['Tag']['hide_tag']
) {
unset($tagCollections[$k]['TagCollectionTag'][$k2]);
}
}
$tagCollections[$k]['TagCollectionTag'] = array_values($tagCollections[$k]['TagCollectionTag']);
}
}
return $single ? $tagCollections[0] : $tagCollections;
}
}

View File

@ -0,0 +1,31 @@
<?php
App::uses('AppModel', 'Model');
class TagCollectionTag extends AppModel
{
public $useTable = 'tag_collection_tags';
public $actsAs = array(
'Trim',
'SysLogLogable.SysLogLogable' => array(
'roleModel' => 'Role',
'roleKey' => 'role_id',
'change' => 'full'
),
'Containable'
);
public $belongsTo = array(
'TagCollection' => array(
'className' => 'TagCollection',
),
'Tag' => array(
'className' => 'Tag',
)
);
public $validate = array(
);
}

View File

@ -163,7 +163,7 @@
);
}
?>
<td class="short">
<td class="short" id="attribute_<?php echo h($object['id']); ?>_galaxy">
<?php
echo $this->element('galaxyQuickViewMini', array(
'mayModify' => $mayModify,

View File

@ -92,7 +92,6 @@
<?php
echo $this->OrgImg->getOrgImg(array('name' => $event['Orgc']['name'], 'id' => $event['Orgc']['id'], 'size' => 24));
?>
&nbsp;
</td>
<?php endif;?>
<?php if ($isSiteAdmin || (Configure::read('MISP.showorgalternate') && Configure::read('MISP.showorg'))): ?>

View File

@ -0,0 +1,48 @@
<tr data-row-id="<?php echo h($item['TagCollection']['id']); ?>">
<td class="short"><?php echo h($item['TagCollection']['id']);?>&nbsp;</td>
<td class="short"><?php echo h($item['TagCollection']['uuid']);?>&nbsp;</td>
<td class="short"><?php echo h($item['TagCollection']['name']);?>&nbsp;</td>
<td class="shortish">
<div class="attributeTagContainer" id="#Tag_Collection_<?php echo h($item['TagCollection']['id']);?>_tr .attributeTagContainer">
<?php
echo $this->element(
'ajaxTagCollectionTags',
array(
'attributeId' => $item['TagCollection']['id'],
'attributeTags' => $item['TagCollectionTag'],
'tagAccess' => ($isSiteAdmin || $me['org_id'] == $item['TagCollection']['org_id']),
'context' => 'tagCollection',
'tagCollection' => $item
)
);
?>
</div>
</td>
<td class="shortish">
<?php
echo $this->element('galaxyQuickViewMini', array(
'mayModify' => ($isSiteAdmin || $me['org_id'] == $item['TagCollection']['org_id']),
'isAclTagger' => true,
'data' => $item['Galaxy'],
'target_id' => h($item['TagCollection']['id']),
'target_type' => 'tag_collection'
));
?>
</td>
<td class="short"><span class="icon-<?php echo $item['TagCollection']['all_orgs'] ? 'ok' : 'remove'; ?>">&nbsp;</span></td>
<td class="short" ondblclick="document.location.href ='<?php echo $baseurl . "/events/index/searchorg:" . $item['Organisation']['id'];?>'">
<?php
echo $this->OrgImg->getOrgImg(array('name' => $item['Organisation']['name'], 'id' => $item['Organisation']['id'], 'size' => 24));
?>
</td>
<td class="short"><?php echo empty($item['User']['email']) ? '&nbsp;' : h($item['User']['email']);?>&nbsp;</td>
<td><?php echo h($item['TagCollection']['description']);?>&nbsp;</td>
<td class="short action-links">
<?php
if ($isSiteAdmin || $me['org_id'] == $item['TagCollection']['org_id']) {
echo $this->Html->link('', array('action' => 'edit', $item['TagCollection']['id']), array('class' => 'icon-edit', 'title' => 'Edit'));
echo $this->Form->postLink('', array('action' => 'delete', $item['TagCollection']['id']), array('class' => 'icon-trash', 'title' => 'Delete'), __('Are you sure you want to delete "%s"?', $item['TagCollection']['name']));
}
?>
</td>
</tr>

View File

@ -39,7 +39,7 @@
if ($full) {
$addTagButton = sprintf(
'<button id="addTagButton" class="btn btn-inverse noPrint" style="line-height:10px; padding: 4px 4px;" onClick="getPopup(%s);">+</button>',
sprintf("'%s/true', 'tags', 'selectTaxonomy'", h($attributeId))
sprintf("'%s/attributes', 'tags', 'selectTaxonomy'", h($attributeId))
);
}
echo $addTagButton;

View File

@ -0,0 +1,36 @@
<div style="width:100%;display:inline-block;">
<?php
if (empty($context)) {
$context = 'event';
}
$full = $isAclTagger && $tagAccess;
foreach ($tagCollection['TagCollectionTag'] as $tag):
if (!isset($tag['Tag'])) $tag = array('Tag' => $tag);
$tagClass = $full ? 'tagFirstHalf' : 'tag';
?>
<div style="padding:1px; overflow:hidden; white-space:nowrap; display:flex; float:left; margin-right:2px;">
<div class="<?php echo $tagClass; ?>" style="display:inline-block; background-color:<?php echo h($tag['Tag']['colour']);?>;color:<?php echo $this->TextColour->getTextColour($tag['Tag']['colour']);?>"><?php echo h($tag['Tag']['name']); ?></div>
<?php
if ($full):
?>
<div class="tagSecondHalf useCursorPointer noPrint" title="<?php echo __('Remove tag');?>" role="button" tabindex="0" aria-label="<?php echo __('Remove tag');?>" onClick="removeObjectTagPopup('tag_collection', '<?php echo h($tagCollection['TagCollection']['id']); ?>', '<?php echo h($tag['Tag']['id']); ?>');">x</div>
<?php
endif;
?>
</div>
<?php
endforeach;
?>
<div style="float:left">
<?php
$addTagButton = '&nbsp;';
if ($full) {
$addTagButton = sprintf(
'<button id="addTagButton" class="btn btn-inverse noPrint" style="line-height:10px; padding: 4px 4px;" onClick="getPopup(%s);">+</button>',
sprintf("'%s/tag_collection', 'tags', 'selectTaxonomy'", h($tagCollection['TagCollection']['id']))
);
}
echo $addTagButton;
?>
</div>
</div>

View File

@ -0,0 +1,66 @@
<?php
$this->Paginator->options(array(
'update' => '.span12',
'evalScripts' => true,
'before' => '$(".progress").show()',
'complete' => '$(".progress").hide()',
));
$title = sprintf('<h2>%s</h2>', Inflector::humanize($controller));
if (!empty($description)) {
$description = sprintf('<p>%s</p>', Inflector::humanize($description));
} else {
$description = '';
}
$pagination = sprintf(
'<div class="pagination"><ul>%s%s%s</ul></div>',
$this->Paginator->prev('&laquo; ' . __('previous'), array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'prev disabled', 'escape' => false, 'disabledTag' => 'span')),
$this->Paginator->numbers(array('modulus' => 20, 'separator' => '', 'tag' => 'li', 'currentClass' => 'active', 'currentTag' => 'span')),
$this->Paginator->next(__('next') . ' &raquo;', array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'next disabled', 'escape' => false, 'disabledTag' => 'span'))
);
$table_headers = '';
foreach ($headers as $header => $data) {
if (!empty($data['sort'])) {
if (!empty($data['alias'])) {
$header_data = $this->Paginator->sort($header, $data['alias']);
} else {
$header_data = $this->Paginator->sort($header);
}
} else {
if (!empty($data['alias'])) {
$header_data = $data['alias'];
} else {
$header_data = Inflector::humanize(h($header));
}
}
$action = ($header === 'Actions') ? ' class="actions"' : '';
$table_headers .= '<th' . $action . '>' . $header_data . '</th>';
}
$table_contents = '';
foreach ($items as $item) {
$table_contents .= $this->element($row_path, array(
'item' => $item
));
}
$table = sprintf(
'<table class="table table-striped table-hover table-condensed">%s%s</table>',
$table_headers,
$table_contents
);
$pagination_details = sprintf(
'<p>%s</p>',
$this->Paginator->counter(
array(
'format' => __('Page {:page} of {:pages}, showing {:current} records out of {:count} total, starting on record {:start}, ending on {:end}')
)
)
);
echo sprintf(
'<div class="%s index">%s%s%s%s%s%s</div>',
$controller,
$title,
$description,
$pagination,
$table,
$pagination_details,
$pagination
);

View File

@ -0,0 +1,59 @@
<?php
$this->Paginator->options(array(
'update' => '.span12',
'evalScripts' => true,
'before' => '$(".progress").show()',
'complete' => '$(".progress").hide()',
));
$title = sprintf('<h2>%s index</h2>', Inflector::humanize($controller));
if (!empty($description)) {
$description = sprintf('<p>%s</p>', Inflector::humanize($description));
} else {
$description = '';
}
$pagination = sprintf(
'<div class="pagination"><ul>%s%s%s</ul></div>',
$this->Paginator->prev('&laquo; ' . __('previous'), array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'prev disabled', 'escape' => false, 'disabledTag' => 'span')),
$this->Paginator->numbers(array('modulus' => 20, 'separator' => '', 'tag' => 'li', 'currentClass' => 'active', 'currentTag' => 'span')),
$this->Paginator->next(__('next') . ' &raquo;', array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'next disabled', 'escape' => false, 'disabledTag' => 'span'))
);
$table_headers = '';
foreach ($headers as $header => $data) {
if (!empty($data['sort'])) {
if (!empty($data['alias'])) {
$header_data = $this->Paginator->sort($header, $data['alias']);
} else {
$header_data = $this->Paginator->sort($header);
}
} else {
$header_data = '<th>' . h($header) . '</th>';
}
$table_headers .= $header_data;
}
$table_contents = $this->element($row_path, array(
'items' => $items
));
$table = sprintf(
'<table class="table table-striped table-hover table-condensed">%s%s</table>',
$table_header,
$table_contents
);
$pagination_details = sprintf(
'<p>%s</p>',
$this->Paginator->counter(
array(
'format' => __('Page {:page} of {:pages}, showing {:current} records out of {:count} total, starting on record {:start}, ending on {:end}')
)
)
);
echo sprintf(
'<div class="%s index">%s%s%s%s%s%s</div>',
$controller,
$title,
$description,
$pagination,
$table,
$pagination_details,
$pagination
);
echo $this->element('side_menu', array('menuList' => 'whitelist', 'menuItem' => 'index'));

View File

@ -33,6 +33,7 @@
<li><a href="<?php echo $baseurl;?>/events/proposalEventIndex"><?php echo __('Events with proposals');?></a></li>
<li class="divider"></li>
<li><a href="<?php echo $baseurl;?>/tags/index"><?php echo __('List Tags');?></a></li>
<li><a href="<?php echo $baseurl;?>/tag_collections/index"><?php echo __('List Tag Collections');?></a></li>
<?php if ($isAclTagEditor): ?>
<li><a href="<?php echo $baseurl;?>/tags/add"><?php echo __('Add Tag');?></a></li>
<?php endif; ?>

View File

@ -181,6 +181,25 @@
}
break;
case 'tag-collections':
echo $this->element('/side_menu_link', array(
'url' => '/tag_collections/index',
'text' => __('List Tag Collections')
));
if ($isAclTagEditor) {
echo $this->element('/side_menu_link', array(
'url' => '/tag_collections/add',
'text' => __('Add Tag Collection')
));
if (($menuItem === 'edit')) {
echo $this->element('/side_menu_link', array(
'url' => '/tag_collections/edit/' . $id,
'text' => __('Add Tag Collection')
));
}
}
break;
case 'event-collection':
echo $this->element('/side_menu_link', array(
'element_id' => 'index',

View File

@ -0,0 +1,26 @@
<?php
$mayModify = (
($isAclModify && $object['Event']['orgc_id'] == $me['org_id'])
);
if ($scope == 'event') {
echo sprintf('<h4 class="blue">%s</h4>', __('Galaxies'));
$element = 'galaxyQuickView';
} else if ($scope == 'attribute') {
$element = 'galaxyQuickViewMini';
}
echo $this->element($element, array(
'mayModify' => $mayModify,
'isAclTagger' => $isAclTagger,
'data' => $object['Galaxy'],
'target_id' => $object['Event']['id'],
'target_type' => $scope
));
?>
<script type="text/javascript">
var showContext = false;
$(document).ready(function () {
$('.addGalaxy').click(function() {
addGalaxyListener(this);
});
});
</script>

View File

@ -1,4 +1,11 @@
<?php
$mayModify = (($isAclModify && $event['Event']['user_id'] == $me['id'] && $event['Event']['orgc_id'] == $me['org_id']) || ($isAclModifyOrg && $event['Event']['orgc_id'] == $me['org_id']));
echo $this->element('ajaxTags', array('event' => $event, 'tags' => $tags, 'tagAccess' => ($isSiteAdmin || $mayModify || $me['org_id'] == $event['Event']['org_id'])));
$mayModify = (
($isAclModify && $event['Event']['user_id'] == $me['id'] && $event['Event']['orgc_id'] == $me['org_id']) ||
($isAclModifyOrg && $event['Event']['orgc_id'] == $me['org_id'])
);
echo $this->element('ajaxTags', array(
'event' => $event,
'tags' => $tags,
'tagAccess' => ($isSiteAdmin || $mayModify)
));
?>

View File

@ -9,14 +9,9 @@ foreach ($events as $key => $event) {
$events[$key]['GalaxyCluster'] = $event['GalaxyCluster'];
}
if (isset($event['EventTag'])) $events[$key]['EventTag'] = $event['EventTag'];
if (!empty($events[$key]['SharingGroup'])) $events[$key]['SharingGroup'] = $event['SharingGroup'];
// cleanup the array from things we do not want to expose
unset($events[$key]['user_id']);
// hide the org field if we are not in showorg mode
if (!Configure::read('MISP.showorg')) {
unset($events[$key]['Org']);
unset($events[$key]['Orgc']);
if (!empty($event['SharingGroup'])) {
$events[$key]['SharingGroup'] = $event['SharingGroup'];
}
unset($events[$key]['user_id']);
}
echo json_encode($events);

View File

@ -43,7 +43,7 @@
});
$('.clusterSelectChoice').click(function() {
quickSubmitGalaxyForm($(this).data('target-type') + '/' + $(this).data('target-id'), $(this).data('cluster-id'));
quickSubmitGalaxyForm($(this).data('target-id'), $(this).data('cluster-id'), $(this).data('target-type'));
});
$('#clusterFilterField').keyup(function() {
var filterString = $("#clusterFilterField").val().toLowerCase();

View File

@ -0,0 +1,27 @@
<div class="roles form">
<?php echo $this->Form->create('TagCollection'); ?>
<fieldset>
<?php
if ($action === 'add') {
echo sprintf('<legend>%s</legend>', __('Add Tag Collection'));
} else {
echo sprintf('<legend>%s</legend>', __('Edit Tag Collection'));
}
echo $this->Form->input('name', array('class' => 'span6'));
echo '<div class="input clear"></div>';
echo $this->Form->input('description', array('class' => 'span6'));
echo '<div class="input clear"></div>';
echo $this->Form->input('all_orgs', array(
'type' => 'checkbox',
'label' => __('Visible to all orgs')
));
?>
</fieldset>
<?php
echo $this->Form->button(__('Submit'), array('class' => 'btn btn-primary'));
echo $this->Form->end();
?>
</div>
<?php
echo $this->element('side_menu', array('menuList' => 'tag-collections', 'menuItem' => 'add'));
?>

View File

@ -0,0 +1,11 @@
<?php
echo $this->element('TagCollections/index_row');
?>
<script type="text/javascript">
$(document).ready(function() {
$('.addGalaxy').click(function() {
addGalaxyListener(this);
});
});
</script>

View File

@ -0,0 +1,28 @@
<?php
echo $this->element('generic_table', array(
'items' => $list,
'controller' => 'tag_collections',
'headers' => array(
'id' => array('sort' => 1),
'uuid' => array('sort' => 1),
'name' => array('sort' => 1),
'tags' => array(),
'galaxies' => array(),
'all_orgs' => array(),
'org_id' => array('alias' => 'Organisation'),
'user_id' => array('alias' => 'User'),
'description' => array(),
'Actions' => array()
),
'row_path' => 'TagCollections/index_row'
));
echo $this->element('side_menu', array('menuList' => 'tag-collections', 'menuItem' => 'index'));
?>
<script type="text/javascript">
$(document).ready(function() {
$('.addGalaxy').click(function() {
addGalaxyListener(this);
});
});
</script>

View File

@ -1,11 +1,14 @@
<div class="popover_choice select_tag">
<legend><?php echo __('Select Tag');?></legend>
<div style="display:none;">
<?php
if (isset($attributeTag)) {
if ($scope === 'attributes') {
echo $this->Form->create('Attribute', array('url' => '/attributes/addTag/' . $object_id, 'style' => 'margin:0px;'));
} else {
} elseif ($scope === 'event') {
echo $this->Form->create('Event', array('url' => '/events/addTag/' . $object_id, 'style' => 'margin:0px;'));
} elseif ($scope === 'tag_collection') {
echo $this->Form->create('TagCollection', array('url' => '/tag_collections/addTag/' . $object_id, 'style' => 'margin:0px;'));
}
echo $this->Form->input('attribute_ids', array('style' => 'display:none;', 'label' => false));
echo $this->Form->input('tag', array('value' => 0));
@ -17,18 +20,32 @@
</div>
<div class="popover_choice_main" id ="popover_choice_main">
<table style="width:100%;">
<?php foreach ($options as $k => &$option): ?>
<tr style="border-top:1px solid black;" class="templateChoiceButton shown" id="field_<?php echo h($k); ?>">
<?php if (isset($attributeTag)): ?>
<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="quickSubmitAttributeTagForm('<?php echo h($object_id);?>', '<?php echo h($k); ?>');" title="<?php echo h($expanded[$k]);?>" role="button" tabindex="0" aria-label="Attach tag <?php echo h($option); ?>"><?php echo h($option); ?></td>
<?php else: ?>
<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="quickSubmitTagForm('<?php echo h($object_id);?>', '<?php echo h($k); ?>');" title="<?php echo h($expanded[$k]);?>" role="button" tabindex="0" aria-label="<?php echo __('Attach tag');?> <?php echo h($option); ?>"><?php echo h($option); ?></td>
<?php endif; ?>
<?php
foreach ($options as $k => &$option):
$choice_id = $k;
if ($taxonomy_id === 'collections') {
$choice_id = 'collection_' . $choice_id;
}
?>
<tr style="border-top:1px solid black;" class="templateChoiceButton shown" id="field_<?php echo h($choice_id); ?>">
<?php
$onClickForm = 'quickSubmitTagForm';
if ($scope === 'attributes') {
$onClickForm = 'quickSubmitAttributeTagForm';
}
if ($scope === 'tag_collection') {
$onClickForm = 'quickSubmitTagCollectionTagForm';
}
echo '<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="' . $onClickForm .
'(\'' . h($object_id) . '\', \'' . h($choice_id) . '\');" title="' . h($expanded[$k]) . '" role="button" tabindex="0" aria-label="' .
__('Attach tag') . ' ' . h($option) . '">' . h($option) . '</td>';
?>
</tr>
<?php endforeach; ?>
</table>
</div>
<div role="button" tabindex="0" aria-label="<?php echo __('Return to taxonomy selection');?>" class="popover-back useCursorPointer" onClick="getPopup('<?php echo h($object_id); if (isset($attributeTag)) echo '/true'; ?>', 'tags', 'selectTaxonomy');" title="<?php echo __('Select Taxonomy');?>"><?php echo __('Back to Taxonomy Selection');?></div>
<div role="button" tabindex="0" aria-label="<?php echo __('Return to taxonomy selection');?>" class="popover-back useCursorPointer" onClick="getPopup('<?php echo h($object_id) . '/' . h($scope); ?>', 'tags', 'selectTaxonomy');" title="<?php echo __('Select Taxonomy');?>"><?php echo __('Back to Taxonomy Selection');?></div>
<div role="button" tabindex="0" aria-label="<?php echo __('Cancel');?>" class="templateChoiceButton templateChoiceButtonLast" onClick="cancelPopoverForm();"><?php echo __('Cancel');?></div>
</div>
<script type="text/javascript">
@ -64,4 +81,4 @@
resizePopoverBody();
});
</script>
<?php echo $this->Html->script('tag-selection-keyboard-navigation.js'); ?>
<?php echo $this->Html->script('tag-selection-keyboard-navigation.js'); ?>

View File

@ -5,22 +5,61 @@
</div>
<div class="popover_choice_main" id ="popover_choice_main">
<table style="width:100%;">
<?php if ($favourites): ?>
<tr style="border-bottom:1px solid black;" class="templateChoiceButton">
<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="getPopup('<?php echo h($object_id); ?>/favourites<?php if (isset($attributeTag)) echo '/true' ?>', 'tags', 'selectTag');"><?php echo __('Favourite Tags');?></td>
</tr>
<?php endif;?>
<tr style="border-bottom:1px solid black;" class="templateChoiceButton">
<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="getPopup('<?php echo h($object_id); ?>/0<?php if (isset($attributeTag)) echo '/true'; ?>', 'tags', 'selectTag');"><?php echo __('Custom Tags');?></td>
</tr>
<tr style="border-bottom:1px solid black;" class="templateChoiceButton">
<td id="allTags" style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" data-url="<?php echo h($object_id); ?>/all<?php if (isset($attributeTag)) echo '/true/'; else echo '/false/'; ?>" onClick="getPopup(this.getAttribute('data-url') + $('#filterField').val(), 'tags', 'selectTag');"><?php echo __('All Tags');?></td>
</tr>
<?php foreach ($options as $k => &$option): ?>
<tr style="border-bottom:1px solid black;" class="templateChoiceButton">
<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%;" onClick="getPopup('<?php echo h($object_id); ?>/<?php echo h($k); if (isset($attributeTag)) echo '/true'; ?>', 'tags', 'selectTag');"><?php echo __('Taxonomy Library');?>: <?php echo h($option); ?></td>
</tr>
<?php endforeach; ?>
<?php
if ($favourites) {
echo sprintf(
'<tr style="border-bottom:1px solid black;" class="templateChoiceButton">%s</tr>',
sprintf(
'<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%%;" onClick="getPopup(\'%s/favourites/%s\', \'tags\', \'selectTag\');">%s</td>',
h($object_id),
h($scope),
__('Favourite Tags')
)
);
}
if ($scope !== 'tag_collection') {
echo sprintf(
'<tr style="border-bottom:1px solid black;" class="templateChoiceButton">%s</tr>',
sprintf(
'<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%%;" onClick="getPopup(\'%s/collections/%s\', \'tags\', \'selectTag\');">%s</td>',
h($object_id),
h($scope),
__('Tag Collections')
)
);
}
echo sprintf(
'<tr style="border-bottom:1px solid black;" class="templateChoiceButton">%s</tr>',
sprintf(
'<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%%;" onClick="getPopup(\'%s/0/%s\', \'tags\', \'selectTag\');">%s</td>',
h($object_id),
h($scope),
__('Custom Tags')
)
);
echo sprintf(
'<tr style="border-bottom:1px solid black;" class="templateChoiceButton">%s</tr>',
sprintf(
'<td id="allTags" style="padding-left:10px;padding-right:10px; text-align:center;width:100%%;" data-url="%s/all/%s" onClick="getPopup(this.getAttribute(\'data-url\') + $(\'#filterField\').val(), \'tags\', \'selectTag\');">%s</td>',
h($object_id),
h($scope),
__('All Tags')
)
);
foreach ($options as $k => &$option) {
echo sprintf(
'<tr style="border-bottom:1px solid black;" class="templateChoiceButton">%s</tr>',
sprintf(
'<td style="padding-left:10px;padding-right:10px; text-align:center;width:100%%;" onClick="getPopup(\'%s/%s/%s\', \'tags\', \'selectTag\');">%s: %s</td>',
h($object_id),
h($k),
h($scope),
__('Taxonomy Library'),
h($option)
)
);
}
?>
</table>
</div>
<div class="templateChoiceButton templateChoiceButtonLast" onClick="cancelPopoverForm();"><?php echo __('Cancel');?></div>
@ -50,7 +89,7 @@
}
}
}, 500);
}
$('#filterField').keyup(onKeyUp);

View File

@ -567,11 +567,13 @@ function quickSubmitTagForm(event_id, tag_id) {
},
success:function (data, textStatus) {
loadEventTags(event_id);
loadGalaxies(event_id, 'event');
handleGenericAjaxResponse(data);
},
error:function() {
showMessage('fail', 'Could not add tag.');
loadEventTags(event_id);
loadGalaxies(event_id, 'event');
},
complete:function() {
$("#popover_form").fadeOut();
@ -599,12 +601,14 @@ function quickSubmitAttributeTagForm(attribute_id, tag_id) {
updateIndex(0, 'event');
} else {
loadAttributeTags(attribute_id);
loadGalaxies(attribute_id, 'attribute');
}
handleGenericAjaxResponse(data);
},
error:function() {
showMessage('fail', 'Could not add tag.');
loadAttributeTags(attribute_id);
loadGalaxies(attribute_id, 'attribute');
},
complete:function() {
$("#popover_form").fadeOut();
@ -617,6 +621,46 @@ function quickSubmitAttributeTagForm(attribute_id, tag_id) {
return false;
}
function quickSubmitTagCollectionTagForm(tag_collection_id, tag_id) {
$('#TagCollectionTag').val(tag_id);
$.ajax({
data: $('#TagCollectionSelectTagForm').closest("form").serialize(),
beforeSend: function (XMLHttpRequest) {
$(".loading").show();
},
success:function (data, textStatus) {
handleGenericAjaxResponse(data);
refreshTagCollectionRow(tag_collection_id);
},
error:function() {
showMessage('fail', 'Could not add tag.');
loadTagCollectionTags(tag_collection_id);
},
complete:function() {
$("#popover_form").fadeOut();
$("#gray_out").fadeOut();
$(".loading").hide();
},
type:"post",
url:"/tag_collections/addTag/" + tag_collection_id
});
return false;
}
function refreshTagCollectionRow(tag_collection_id) {
$.ajax({
type:"get",
url:"/tag_collections/getRow/" + tag_collection_id,
error:function() {
showMessage('fail', 'Could not fetch updates to the modified row.');
},
success: function (data, textStatus) {
$('[data-row-id="' + tag_collection_id + '"]').replaceWith(data);
}
});
}
function handleAjaxEditResponse(data, name, type, id, field, event) {
responseArray = data;
if (type == 'Attribute') {
@ -848,6 +892,32 @@ function loadEventTags(id) {
});
}
function loadGalaxies(id, scope) {
$.ajax({
dataType:"html",
cache: false,
success:function (data, textStatus) {
if (scope == 'event') {
$("#galaxies_div").html(data);
} else if (scope == 'attribute') {
$("#attribute_" + id + "_galaxy").html(data);
}
},
url:"/galaxies/showGalaxies/" + id + "/" + scope,
});
}
function loadTagCollectionTags(id) {
$.ajax({
dataType:"html",
cache: false,
success:function (data, textStatus) {
$(".tagCollectionTagContainer").html(data);
},
url:"/tags/showEventTag/" + id,
});
}
function removeEventTag(event, tag) {
var answer = confirm("Are you sure you want to remove this tag from the event?");
if (answer) {
@ -905,6 +975,8 @@ function removeObjectTag(context, object, tag) {
$("#gray_out").fadeOut();
if (context == 'Attribute') {
loadAttributeTags(object);
} else if (context == 'tag_collection') {
refreshTagCollectionRow(object);
} else {
loadEventTags(object);
}
@ -3223,9 +3295,29 @@ function addGalaxyListener(id) {
getPopup(target_type + '/' + target_id, 'galaxies', 'selectGalaxyNamespace');
}
function quickSubmitGalaxyForm(event_id, cluster_id) {
function quickSubmitGalaxyForm(scope, cluster_id, event_id) {
$('#GalaxyTargetId').val(cluster_id);
$('#GalaxySelectClusterForm').submit();
$.ajax({
data: $('#GalaxySelectClusterForm').closest("form").serialize(),
beforeSend: function (XMLHttpRequest) {
$(".loading").show();
},
success:function (data, textStatus) {
loadGalaxies(event_id, scope);
handleGenericAjaxResponse(data);
},
error:function() {
showMessage('fail', 'Could not add cluster.');
loadGalaxies(event_id, scope);
},
complete:function() {
$("#popover_form").fadeOut();
$("#gray_out").fadeOut();
$(".loading").hide();
},
type:"post",
url: "/galaxies/attachCluster/" + event_id + "/" + scope
});
return false;
}