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

pull/5032/head
mokaddem 2019-08-29 10:52:18 +02:00
commit a5d06d1333
No known key found for this signature in database
GPG Key ID: 164C473F627A06FA
38 changed files with 948 additions and 54 deletions

2
PyMISP

@ -1 +1 @@
Subproject commit b802e202e2da81a96b6ef660dff1115a45135e0e
Subproject commit f133cb9477dab9cd81f8631db8c27af6c0d291c0

View File

@ -378,7 +378,7 @@ class AppController extends Controller
$this->Auth->logout();
throw new MethodNotAllowedException($message);//todo this should pb be removed?
} else {
$this->Flash->error('Warning: MISP is currently disabled for all users. Enable it in Server Settings (Administration -> Server Settings -> MISP tab -> live). An update might also be in progress, you can see the progress in ' , array('params' => array('url' => $baseurl . '/servers/advancedUpdate/', 'urlName' => 'Advanced Update'), 'clear' => 1));
$this->Flash->error('Warning: MISP is currently disabled for all users. Enable it in Server Settings (Administration -> Server Settings -> MISP tab -> live). An update might also be in progress, you can see the progress in ' , array('params' => array('url' => $baseurl . '/servers/updateProgress/', 'urlName' => __('Update Progress')), 'clear' => 1));
}
}
if ($this->Session->check(AuthComponent::$sessionKey)) {

View File

@ -0,0 +1,170 @@
<?php
App::uses('AppController', 'Controller');
class CommunitiesController extends AppController
{
public $components = array('Session', 'RequestHandler');
public function beforeFilter()
{
parent::beforeFilter();
}
public $paginate = array(
'limit' => 60,
'maxLimit' => 9999
);
public function index()
{
$paramsToHarvest = array('context', 'value');
foreach ($paramsToHarvest as $param) {
if (!empty($this->params['named'][$param])) {
${$param} = $this->params['named'][$param];
} else if ($this->request->is('post') && !empty($this->request->data[$param])) {
${$param} = trim($this->request->data[$param]);
} else if ($param === 'context') {
${$param} = 'vetted';
}
}
$filterData = array(
'request' => $this->request,
'paramArray' => array('context', 'value'),
'named_params' => $this->params['named']
);
$exception = false;
$filters = $this->_harvestParameters($filterData, $exception);
if (empty($filters['context'])) {
$filters['context'] = 'vetted';
}
if (!empty($value)) {
$value = strtolower($value);
} else {
$value = false;
}
$community_list = $this->Community->getCommunityList($context, $value);
//foreach ($community)
if ($this->_isRest()) {
return $this->RestResponse->viewData($community_list, $this->response->type());
}
App::uses('CustomPaginationTool', 'Tools');
$customPagination = new CustomPaginationTool();
$customPagination->truncateAndPaginate($community_list, $this->params, $this->modelClass, true);
$this->set('community_list', $community_list);
$this->set('context', $filters['context']);
$this->set('passedArgs', json_encode($this->passedArgs, true));
}
public function view($id)
{
$community = $this->Community->getCommunity($id);
if ($this->_isRest()) {
return $this->RestResponse->viewData($community, $this->response->type());
} else {
$this->set('community', $community);
}
}
public function requestAccess($id)
{
$community = $this->Community->getCommunity($id);
$this->loadModel('User');
$gpgkey = $this->User->find('first', array(
'conditions' => array('User.id' => $this->Auth->user('id')),
'recursive' => -1,
'fields' => array('User.gpgkey')
));
if (!$this->request->is('post')) {
$this->request->data['Server']['email'] = $this->Auth->user('email');
$this->request->data['Server']['org_name'] = $this->Auth->user('Organisation')['name'];
$this->request->data['Server']['org_uuid'] = $this->Auth->user('Organisation')['uuid'];
$this->request->data['Server']['gpgkey'] = $gpgkey['User']['gpgkey'];
} else {
if (empty($this->request->data['Server'])) {
$this->request->data = array('Server' => $this->request->data);
}
$body = sprintf(
'To whom it may concern,
On behalf of my organisation (%s - %s),
I would hereby like to request %saccess to your MISP community:
%s
A brief description of my organisation:
%s
My e-mail address that I wish to use as my username:
%s
%s%s
Thank you in advance!',
$this->request->data['Server']['org_name'],
$this->request->data['Server']['org_uuid'],
empty($this->request->data['Server']['sync']) ? '' : 'synchronisation ',
$community['community_name'],
$this->request->data['Server']['org_description'],
$this->request->data['Server']['email'],
empty($this->request->data['Server']['message']) ? '' : sprintf(
'%sAdditional information:%s%s%s',
PHP_EOL,
PHP_EOL,
$this->request->data['Server']['message'],
PHP_EOL
),
!empty($this->request->data['Server']['anonymise']) ? '' : sprintf(
'%sServer used to issue the request%sServer url: %sServer uuid: %sServer version: %s',
PHP_EOL,
PHP_EOL,
(empty(Configure::read('MISP.external_baseurl')) ? Configure::read('MISP.baseurl') : Configure::read('MISP.external_baseurl')) . PHP_EOL,
Configure::read('MISP.uuid') . PHP_EOL,
$this->mispVersion . PHP_EOL
)
);
$imgPath = APP . WEBROOT_DIR . DS . 'img' . DS . 'orgs' . DS;
$possibleFields = array('id', 'name');
$image = false;
App::uses('File', 'Utility');
foreach ($possibleFields as $field) {
if (isset($options[$field])) {
$file = new File($imgPath . $options[$field] . 'png');
if ($file->exists()) {
$image = $file->read();
break;
}
}
}
if (!empty($image)) {
$params['attachments']['logo.png'] = $image;
}
if (!empty($gpgkey)) {
$params['attachments']['requestor.asc'] = $gpgkey;
}
$params = array();
$params['to'] = $community['email'];
$params['reply-to'] = $this->request->data['Server']['email'];
$params['requestor_gpgkey'] = $this->request->data['Server']['gpgkey'];
$params['gpgkey'] = $community['pgp_key'];
$params['body'] = $body;
$params['subject'] = '[' . $community['community_name'] . '] Requesting MISP access';
$result = $this->User->sendEmailExternal($this->Auth->user(), $params);
$message = $result ? __('Request sent.') : __('Something went wrong and the request could not be sent.');
if ($this->_isRest()) {
if ($result) {
return $this->RestResponse->saveSuccessResponse('Communities', 'requestAccess', $id, false, $message);
} else {
return $this->RestResponse->saveFailResponse('Communities', 'requestAccess', false, $message);
}
} else {
if ($result) {
$this->Flash->success($message);
} else {
$this->Flash->error($message);
}
$this->redirect(array('controller' => 'communities', 'action' => 'view', $id));
}
}
$this->set('community', $community);
}
}

View File

@ -92,6 +92,11 @@ class ACLComponent extends Component
"viewAssociatedTypes" => array('*'),
"linkAttributeTypeToModel" => array('perm_admin', 'perm_decaying')
),
'communities' => array(
'index' => array(),
'requestAccess' => array(),
'view' => array()
),
'eventBlacklists' => array(
'add' => array(),
'delete' => array(),

View File

@ -67,6 +67,9 @@ class EventBlacklistsController extends AppController
public function massDelete()
{
if ($this->request->is('post') || $this->request->is('put')) {
if (!isset($this->request->data['EventBlacklist'])) {
$this->request->data = array('EventBlacklist' => $this->request->data);
}
$ids = $this->request->data['EventBlacklist']['ids'];
$event_ids = json_decode($ids, true);
if (empty($event_ids)) {

View File

@ -2634,6 +2634,7 @@ class EventsController extends AppController
// Users with a GnuPG key will get the mail encrypted, other users will get the mail unencrypted
public function contact($id = null)
{
$id = $this->Toolbox->findIdByUuid($this->Event, $id);
$this->Event->id = $id;
if (!$this->Event->exists()) {
throw new NotFoundException(__('Invalid event'));
@ -2654,7 +2655,10 @@ class EventsController extends AppController
}
}
$creator_only = $this->request->data['Event']['person'];
$creator_only = false;
if (isset($this->request->data['Event']['person'])) {
$creator_only = $this->request->data['Event']['person'];
}
$user = $this->Auth->user();
$user['gpgkey'] = $this->Event->User->getPGP($user['id']);
$user['certif_public'] = $this->Event->User->getCertificate($user['id']);

View File

@ -1251,6 +1251,7 @@ class UsersController extends AppController
uasort($data, function ($a, $b) {
return $b['total'] - $a['total'];
});
$data = array_values($data);
$this->set('data', $data);
$this->set('max', $max);
$this->set('selectedTypes', $selectedTypes);

View File

@ -17,7 +17,7 @@ class CustomPaginationTool
'options' => array(
),
);
$validOptions = array('sort', 'direction', 'page', 'focus');
$validOptions = array('sort', 'direction', 'page', 'focus', 'limit');
if ($model == 'events') {
$validOptions[] = 'attributeFilter';
}
@ -55,12 +55,40 @@ class CustomPaginationTool
$items = array_slice($items, $params['current'] - 1, $params['limit']);
}
public function truncateByQuickFilter(&$items, $value)
{
if (empty($items)) {
return;
}
if ($value === '') {
return;
}
$value = strtolower($value);
foreach ($items as $k => $item) {
$keep = false;
foreach ($item as $field_name => $field_value) {
if (!is_array($field_value)) {
$field_value = array($field_value);
}
foreach ($field_value as $v) {
if (!is_array($v) && strpos(strtolower($v), $value) > -1) {
$keep = true;
}
}
}
if (!$keep) {
unset($items[$k]);
}
}
$items = array_values($items);
}
public function sortArray($items, $params, $escapeReindex = false)
{
if (isset($params['sort'])) {
$sortArray = array();
foreach ($items as $k => $item) {
$sortArray[$k] = empty($item[$params['sort']]) ? '' : $item[$params['sort']];
$sortArray[$k] = !empty(Hash::get($item, $params['sort'])) ? $item[$params['sort']] : '';
}
if (empty($params['options']['direction']) || $params['options']['direction'] == 'asc') {
asort($sortArray);
@ -80,15 +108,15 @@ class CustomPaginationTool
return $items;
}
public function applyRulesOnArray(&$items, $options, $model, $sort = 'id', $focusKey = 'uuid')
public function applyRulesOnArray(&$items, $options, $model, $sort = 'id', $focusKey = 'uuid', $escapeReindex = false)
{
$params = $this->createPaginationRules($items, $options, $model, $sort, $focusKey);
$items = $this->sortArray($items, $params);
$items = $this->sortArray($items, $params, $escapeReindex);
if (!empty($params['options']['focus'])) {
foreach ($items as $k => $item) {
if ($item[$focusKey] == $params['options']['focus']) {
$params['page'] = 1 + intval(floor($k / $params['limit']));
$params['current'] = 1 + ($params['page'] - 1) * 60;
$params['current'] = 1 + ($params['page'] - 1) * $params['limit'];
continue;
}
}
@ -100,6 +128,15 @@ class CustomPaginationTool
return $params;
}
public function truncateAndPaginate(&$items, &$params, $model, $escapeReindex = false)
{
if (!empty($params['named']['searchall'])) {
$this->truncateByQuickFilter($items, $params['named']['searchall']);
}
$passedArgs = $this->applyRulesOnArray($items, $params['named'], 'Feed', 'id', 'uuid', $escapeReindex);
$params->params['paging'] = array($model => $passedArgs);
}
public function cmp($a, $b)
{
$multiplier = 1;

View File

@ -3082,6 +3082,14 @@ class Attribute extends AppModel
);
}
if (isset($options['contain'])) {
// We may use a string instead of an array to ask for everything
// instead of some specific attributes. If so, remove the array from
// params, as we will later add the string.
foreach($options['contain'] as $contain) {
if (gettype($contain) == "string" && isset($params['contain'][$contain])) {
unset($params['contain'][$contain]);
}
}
$params['contain'] = array_merge_recursive($params['contain'], $options['contain']);
}
if (isset($options['page'])) {

97
app/Model/Community.php Normal file
View File

@ -0,0 +1,97 @@
<?php
App::uses('AppModel', 'Model');
class Community extends AppModel
{
public $useTable = false;
public $recursive = -1;
public $actsAs = array(
'Containable',
);
public $validate = array(
);
public function beforeValidate($options = array())
{
parent::beforeValidate();
return true;
}
public function getCommunityList($context, $value)
{
$community_file = new File(APP . 'files/community-metadata/defaults.json');
if (!$community_file->exists()) {
throw new NotFoundException(__('Default community list not found.'));
}
$community_list = $community_file->read();
if (empty($community_list)) {
throw new NotFoundException(__('Default community list empty.'));
}
try {
$community_list = json_decode($community_list, true);
} catch (Exception $e) {
throw new NotFoundException(__('Default community list not in the expected format.'));
}
$fieldsToCheck = array('community_name', 'community_uuid', 'description', 'url', 'sector', 'nationality', 'type_of_community', 'org_uuid', 'org_name', 'rules');
foreach ($community_list as $k => $v) {
if ($v['misp_project_vetted'] === ($context === 'vetted')) {
$community_list[$k]['id'] = $k + 1;
$community_list[$k]['Org'] = array('uuid' => $v['org_uuid'], 'name' => $v['org_name']);
} else {
unset($community_list[$k]);
continue;
}
if (!empty($value)) {
$found = false;
foreach ($fieldsToCheck as $field) {
if (strpos(strtolower($v[$field]), $value) !== false) {
$found = true;
continue;
}
}
if (!$found) {
unset($community_list[$k]);
}
}
}
$community_list = array_values($community_list);
return $community_list;
}
public function getCommunity($id)
{
$community_file = new File(APP . 'files/community-metadata/defaults.json');
if (!$community_file->exists()) {
throw new NotFoundException(__('Default community list not found.'));
}
$community_list = $community_file->read();
if (empty($community_list)) {
throw new NotFoundException(__('Default community list empty.'));
}
try {
$community_list = json_decode($community_list, true);
} catch (Exception $e) {
throw new NotFoundException(__('Default community list not in the expected format.'));
}
foreach ($community_list as $k => $v) {
$community_list[$k]['id'] = $k + 1;
$community_list[$k]['Org'] = array('uuid' => $v['org_uuid'], 'name' => $v['org_name']);
}
$community = false;
$lookupField = 'id';
if (Validation::uuid($id)) {
$lookupField = 'uuid';
}
foreach ($community_list as $s) {
if ($s[$lookupField === 'uuid' ? 'community_uuid' : 'id'] === $id) {
$community = $s;
}
}
if (empty($community)) {
throw new NotFoundException(__('Community not found.'));
}
return $community;
}
}

View File

@ -4155,20 +4155,45 @@ class Server extends AppModel
public function dbSpaceUsage()
{
$sql = sprintf(
'select table_name, sum((data_length+index_length)/1024/1024) AS used, sum(data_free)/1024/1024 reclaimable from information_schema.tables where table_schema = %s group by table_name;',
"'" . $this->getDataSource()->config['database'] . "'"
);
$sqlResult = $this->query($sql);
$result = array();
foreach ($sqlResult as $temp) {
foreach ($temp[0] as $k => $v) {
$temp[0][$k] = round($v, 2) . 'MB';
$dataSource = $this->getDataSource()->config['datasource'];
if ($dataSource == 'Database/Mysql') {
$sql = sprintf(
'select table_name, sum((data_length+index_length)/1024/1024) AS used, sum(data_free)/1024/1024 reclaimable from information_schema.tables where table_schema = %s group by table_name;',
"'" . $this->getDataSource()->config['database'] . "'"
);
$sqlResult = $this->query($sql);
$result = array();
foreach ($sqlResult as $temp) {
foreach ($temp[0] as $k => $v) {
$temp[0][$k] = round($v, 2) . 'MB';
}
$temp[0]['table'] = $temp['tables']['table_name'];
$result[] = $temp[0];
}
$temp[0]['table'] = $temp['tables']['table_name'];
$result[] = $temp[0];
return $result;
}
return $result;
else if ($dataSource == 'Database/Postgres') {
$sql = sprintf(
'select table_name as table, pg_total_relation_size(%s||%s||table_name) as used from information_schema.tables where table_schema = %s group by table_name;',
"'" . $this->getDataSource()->config['database'] . "'",
"'.'",
"'" . $this->getDataSource()->config['database'] . "'"
);
$sqlResult = $this->query($sql);
$result = array();
foreach ($sqlResult as $temp) {
foreach ($temp[0] as $k => $v) {
if ($k == "table") {
continue;
}
$temp[0][$k] = round($v / 1024 / 1024, 2) . 'MB';
}
$temp[0]['reclaimable'] = '0MB';
$result[] = $temp[0];
}
return $result;
}
}
public function writeableDirsDiagnostics(&$diagnostic_errors)

View File

@ -739,6 +739,64 @@ class User extends AppModel
return $users;
}
public function sendEmailExternal($user, $params)
{
$this->Log = ClassRegistry::init('Log');
if (Configure::read('MISP.disable_emailing')) {
$this->Log->create();
$this->Log->save(array(
'org' => 'SYSTEM',
'model' => 'User',
'model_id' => $user['id'],
'email' => $user['email'],
'action' => 'email',
'title' => 'Email to ' . $user['email'] . ', titled "' . $params['subject'] . '" failed. Reason: Emailing is currently disabled on this instance.',
'change' => null,
));
return true;
}
$params['body'] = str_replace('\n', PHP_EOL, $params['body']);
$Email = new CakeEmail();
$recipient = array('User' => array('email' => $params['to']));
$failed = false;
if (!empty($params['gpgkey'])) {
$recipient['User']['gpgkey'] = $params['gpgkey'];
$encryptionResult = $this->__encryptUsingGPG($Email, $params['body'], $params['subject'], $recipient);
if (isset($encryptionResult['failed'])) {
$failed = true;
}
if (isset($encryptionResult['failureReason'])) {
$failureReason = $encryptionResult['failureReason'];
}
}
if (!$failed) {
$replyToLog = '';
$user = array('User' => $user);
$attachments = array();
$Email->replyTo($params['reply-to']);
if (!empty($params['requestor_gpgkey'])) {
$attachments['gpgkey.asc'] = array(
'data' => $params['requestor_gpgkey']
);
}
$Email->from(Configure::read('MISP.email'));
$Email->returnPath(Configure::read('MISP.email'));
$Email->to($params['to']);
$Email->subject($params['subject']);
$Email->emailFormat('text');
if (!empty($params['attachments'])) {
foreach ($params['attachments'] as $key => $value) {
$attachments[$k] = array('data' => $value);
}
}
$Email->attachments($attachments);
$result = $Email->send($params['body']);
$Email->reset();
return $result;
}
return false;
}
// all e-mail sending is now handled by this method
// Just pass the user ID in an array that is the target of the e-mail along with the message body and the alternate message body if the message cannot be encrypted
// the remaining two parameters are the e-mail subject and a secondary user object which will be used as the replyto address if set. If it is set and an encryption key for the replyTo user exists, then his/her public key will also be attached
@ -833,16 +891,21 @@ class User extends AppModel
return false;
}
private function __finaliseAndSendEmail($replyToUser, &$Email, &$replyToLog, $user, $subject, $body)
private function __finaliseAndSendEmail($replyToUser, &$Email, &$replyToLog, $user, $subject, $body, $additionalAttachments = false)
{
// If the e-mail is sent on behalf of a user, then we want the target user to be able to respond to the sender
// For this reason we should also attach the public key of the sender along with the message (if applicable)
$attachments = array();
if ($replyToUser != false) {
$Email->replyTo($replyToUser['User']['email']);
if (!empty($replyToUser['User']['gpgkey'])) {
$Email->attachments(array('gpgkey.asc' => array('data' => $replyToUser['User']['gpgkey'])));
$attachments['gpgkey.asc'] = array(
'data' => $replyToUser['User']['gpgkey']
);
} elseif (!empty($replyToUser['User']['certif_public'])) {
$Email->attachments(array($replyToUser['User']['email'] . '.pem' => array('data' => $replyToUser['User']['certif_public'])));
$attachments[$replyToUser['User']['email'] . '.pem'] = array(
'data' => $replyToUser['User']['certif_public']
);
}
$replyToLog = 'from ' . $replyToUser['User']['email'];
}
@ -851,6 +914,12 @@ class User extends AppModel
$Email->to($user['User']['email']);
$Email->subject($subject);
$Email->emailFormat('text');
if (!empty($additionalAttachments)) {
foreach ($additionalAttachments as $key => $value) {
$attachments[$k] = array('data' => $value);
}
}
$Email->attachments($attachments);
$result = $Email->send($body);
$Email->reset();
return $result;

View File

@ -0,0 +1,101 @@
<?php
echo '<div class="index">';
echo $this->element('/genericElements/IndexTable/index_table', array(
'data' => array(
'data' => $community_list,
'top_bar' => array(
'children' => array(
array(
'type' => 'simple',
'children' => array(
array(
'active' => $context === 'vetted',
'url' => $baseurl . '/communities/index/context:vetted',
'text' => __('Vetted by the MISP-project team'),
),
array(
'active' => $context === 'unvetted',
'url' => $baseurl . '/communities/index/context:unvetted',
'text' => __('Unvetted'),
)
)
),
array(
'type' => 'search',
'button' => __('Filter'),
'placeholder' => __('Enter value to search'),
'data' => '',
'searchKey' => 'value'
)
)
),
'fields' => array(
array(
'name' => __('Id'),
'sort' => 'id',
'class' => 'short',
'data_path' => 'id',
),
array(
'name' => __('Vetted'),
'element' => 'boolean',
'class' => 'short',
'data_path' => 'misp_project_vetted',
),
array(
'name' => __('Host org'),
'sort' => 'org_name',
'class' => 'short',
'element' => 'org',
'data_path' => 'Org',
),
array(
'name' => __('Community name'),
'sort' => 'community_name',
'class' => 'short',
'data_path' => 'community_name',
),
array(
'name' => __('Description'),
'data_path' => 'description',
)
),
'title' => __('Communities index'),
'description' => __('You can find a list of communities below that chose to advertise their existence to the general MISP user-base.\nRequesting access to any of those communities is of course no guarantee of being permitted access, it is simply meant to simplify to means of finding the various communities that one may be eligible for. Get in touch with the misp-project maintainers if you would like your community to be included in the list.'),
'actions' => array(
array(
'url' => '/communities/view',
'url_params_data_paths' => array(
'community_uuid'
),
'icon' => 'eye'
),
array(
'url' => '/communities/requestAccess',
'url_params_data_paths' => array(
'community_uuid'
),
'icon' => 'comments'
)
)
)
));
echo '</div>';
echo $this->element('/genericElements/SideMenu/side_menu', array('menuList' => 'sync', 'menuItem' => 'list_communities'));
?>
<script type="text/javascript">
var passedArgsArray = <?php echo $passedArgs; ?>;
if (passedArgsArray['context'] === undefined) {
passedArgsArray['context'] = 'pending';
}
$(document).ready(function() {
$('#quickFilterButton').click(function() {
runIndexQuickFilter('/context:' + passedArgsArray['context']);
});
$('#quickFilterField').on('keypress', function (e) {
if(e.which === 13) {
runIndexQuickFilter('/context:' + passedArgsArray['context']);
}
});
});
</script>

View File

@ -0,0 +1,68 @@
<div class="attributes form">
<?php
echo $this->Form->create('Server', array('id', 'url' => '/communities/requestAccess/' . $community['community_uuid']));
echo sprintf(
'<fieldset><legend>%s</legend><p style="width:550px;">%s</p>%s</fieldset>%s',
'Request access to ' . h($community['community_name']),
__('Describe both yourself and your organisation as best as you can - keep in mind this information is to be used by the hosts of the community you are requesting access to in order to determine whether you\'re a good fit for their community. The sending server\'s basic metadata is included by default, you can opt out using the "anonymise" checkbox (server url, uuid, version are shared otherwise - though this can be a useful step in establishing trust.).'),
(
$this->Form->input('email', array(
'label' => __('Requestor E-mail address'),
'div' => 'input clear',
'class' => 'input-xxlarge'
)) .
$this->Form->input('org_name', array(
'label' => __('Organisation name'),
'div' => 'input clear',
'class' => 'input-xxlarge'
)) .
$this->Form->input('org_uuid', array(
'label' => __('Organisation uuid'),
'div' => 'input clear',
'class' => 'input-xxlarge'
)) .
$this->Form->input('org_description', array(
'label' => __('Description of the requestor organisation'),
'div' => 'input clear',
'type' => 'textarea',
'class' => 'input-xxlarge'
)) .
$this->Form->input('message', array(
'label' => __('Message to the community host organisation'),
'div' => 'input clear',
'type' => 'textarea',
'class' => 'input-xxlarge'
)) .
$this->Form->input('gpgkey', array(
'label' => __('PGP public key'),
'div' => 'input clear',
'type' => 'textarea',
'class' => 'input-xxlarge'
)) .
$this->element('/genericElements/Forms/clear') .
$this->Form->input('sync', array(
'label' => __('Request sync access'),
'type' => 'checkbox'
)) .
$this->element('/genericElements/Forms/clear') .
$this->Form->input('anonymise', array(
'label' => __('Anonymise information on the server used to issue the request'),
'type' => 'checkbox'
))
),
$this->Form->button('Submit', array(
'class' => 'btn btn-primary',
'div' => 'input clear',
)) .
$this->Form->end()
);
?>
</div>
<?php
echo $this->element('/genericElements/SideMenu/side_menu', array('menuList' => 'sync', 'menuItem' => 'request_community_access'));
?>
<script type="text/javascript">
$(document).ready(function() {
});
</script>
<?php echo $this->Js->writeBuffer();

View File

@ -0,0 +1,60 @@
<div class="communities view">
<?php
$table_data = array();
$table_data[] = array('key' => __('Id'), 'value' => $community['id']);
$table_data[] = array('key' => __('UUID'), 'value' => $community['community_uuid']);
$table_data[] = array('key' => __('Name'), 'value' => $community['community_name']);
$table_data[] = array('key' => __('Host organisation'), 'value' => $community['org_name'] . '(' . $community['org_uuid'] . ')');
$table_data[] = array(
'key' => __('Vetted by MISP-project'),
'html' => sprintf(
'<dd><span class="%s bold">%s</span></dd>',
$community['misp_project_vetted'] ? 'green' : 'red',
$community['misp_project_vetted'] ? __('Yes') : __('No')
)
);
$optional_fields = array(
'type_of_community', 'description', 'rules', 'email', 'sector', 'nationality', 'eligibility', 'pgp_key'
);
foreach ($optional_fields as $field) {
if (!empty($community[$field])) {
$table_data[] = array('key' => Inflector::humanize($field), 'value' => $community[$field]);
}
}
//misp-project.org/org-logos/uuid.png
echo sprintf(
'<div class="row-fluid"><div class="span8" style="margin:0px;">%s</div></div>',
sprintf(
'%s<h2>%s</h2>%s',
sprintf(
'<img src="https://misp-project.org/org-logos/%s.png" title="%s" aria-label="%s"/>',
h($community['org_uuid']),
h($community['org_name']),
h($community['org_name'])
),
__('Community ') . h($community['community_name']),
$this->element('genericElements/viewMetaTable', array('table_data' => $table_data))
)
);
echo sprintf(
'<a href="%s%s%s" class="btn btn-primary">%s</a>',
$baseurl,
'/communities/requestAccess/',
h($community['community_uuid']),
__('Request Access')
);
?>
</div>
<?php
echo $this->element('/genericElements/SideMenu/side_menu', array('menuList' => 'sync', 'menuItem' => 'view_community'));
?>
<script type="text/javascript">
<?php
$startingTab = 'description';
if (!$local) $startingTab = 'events';
?>
$(document).ready(function () {
organisationViewContent('<?php echo $startingTab; ?>', '<?php echo h($id);?>');
});
</script>

View File

@ -0,0 +1 @@
<div class="input clear"></div>

View File

@ -0,0 +1,43 @@
<?php
echo '<td class="short action-links">';
foreach ($actions as $action) {
$url_param_data_paths = '';
$url = empty($action['url']) ? '#' : h($action['url']);
if (!empty($action['url_params_data_paths'])) {
if (is_array($action['url_params_data_paths'])) {
$temp = array();
foreach ($action['url_params_data_paths'] as $path) {
$temp[] = h(Hash::extract($row, $path)[0]);
}
$url_param_data_paths = implode('/', $temp);
} else {
$url_param_data_paths = h(Hash::extract($row, $action['url_params_data_paths'])[0]);
}
$url .= '/' . $url_param_data_paths;
}
if (isset($action['postLink'])) {
echo $this->Form->postLink(
'',
array(
'url' => $url
),
array(
'class' => $this->FontAwesome->getClass($action['icon']) . ' black ' . (empty($action['class']) ? '' : h($action['class'])),
'title' => empty($action['title']) ? '' : h($action['title']),
'aria-label' => empty($action['aria-label']) ? '' : h($action['aria-label']),
),
empty($action['postLinkConfirm'])? '' : $action['postLinkConfirm']
);
} else {
echo sprintf(
'<a href="%s" class="black %s" title="%s" aria-label="%s" %s></a>',
$url,
$this->FontAwesome->getClass($action['icon']),
empty($action['title']) ? '' : h($action['title']),
empty($action['title']) ? '' : h($action['title']),
empty($action['onclick']) ? '' : sprintf('onclick="%s"', $action['onclick'])
);
}
}
echo '</td>';
?>

View File

@ -0,0 +1,4 @@
<?php
echo h($arrayData[Hash::extract($row, $field['data_path'])[0]]);
?>

View File

@ -0,0 +1,6 @@
<?php
echo sprintf(
'<i class="black fa fa-%s"></i>',
(Hash::extract($row, $field['data_path'])[0]) ? 'check' : 'times'
);
?>

View File

@ -0,0 +1,20 @@
<?php
$correlations = Hash::extract($row, $field['data_path']);
$scope_to_url = array(
'event' => $baseurl . '/events/view'
);
$correlations_html = array();
foreach ($correlations as $id => $name) {
$correlations_html[] = sprintf(
'<a href="%s" title="%s">%s</a>',
sprintf(
'%s/%s',
$scope_to_url[empty($scope) ? 'event' : $scope],
h($id)
),
h($name),
h($id)
);
}
echo implode(' ', $correlations_html);
?>

View File

@ -0,0 +1,15 @@
<?php
$distributionLevel = (Hash::extract($row, $field['data_path'])[0]);
echo sprintf(
'<span class="%s bold">%s</span>',
$distributionLevel == 0 ? 'red' : '',
$distributionLevel != 4 ? $distributionLevels[$distributionLevel] :
sprintf(
'<a href="%s/sharing_groups/view/%s">%s</a>',
$baseurl,
h($row['SharingGroup']['id']),
h($row['SharingGroup']['name'])
)
);
?>

View File

@ -3,7 +3,7 @@
echo sprintf(
'<a href="%s/organisations/view/%s">%s</a>',
$baseurl,
h($org['id']),
empty($org['id']) ? h($org['uuid']) : h($org['id']),
h($org['name'])
);
?>

View File

@ -0,0 +1,6 @@
<?php
echo sprintf(
'<input class="select_attribute" type="checkbox" data-rowid="%s">',
h($k)
);
?>

View File

@ -0,0 +1,4 @@
<?php
$tags = Hash::extract($row, $field['data_path']);
echo $this->element('ajaxTags', array('attributeId' => 0, 'tags' => $tags, 'tagAccess' => false));
?>

View File

@ -0,0 +1,3 @@
<?php
echo h(Hash::extract($row, $field['data_path'])[0]);
?>

View File

@ -9,13 +9,27 @@
$header_data = $paginator->sort($header['sort']);
}
} else {
$header_data = h($header['name']);
if (!empty($header['element']) && $header['element'] === 'selector') {
$header_data = sprintf(
'<input class="%s" type="checkbox" %s>',
empty($header['select_all_class']) ? 'select_all' : $header['select_all_class'],
empty($header['select_all_function']) ? 'onclick="toggleAllAttributeCheckboxes();"' : 'onclick="' . $header['select_all_function'] . '"'
);
} else {
$header_data = h($header['name']);
}
}
$headersHtml .= sprintf(
'<th %s>%s</th>',
empty($header['header_class']) ? '' : 'class="' . h($header['header_class']) . '"',
'<th>%s</th>',
$header_data
);
}
if ($actions) {
$headersHtml .= sprintf(
'<th class="actions">%s</th>',
__('Actions')
);
}
echo $headersHtml;
?>

View File

@ -21,9 +21,14 @@
if (!empty($data['description'])) {
echo sprintf('<p>%s</p>', h($data['description']));
}
if (empty($data['skip_pagination'])) {
echo $this->element('/genericElements/IndexTable/pagination', array('paginator' => $this->Paginator));
if (!empty($data['html'])) {
echo sprintf('<p>%s</p>', $data['html']);
}
$paginationData = array();
if (!empty($data['paginationBaseurl'])) {
$paginationData['paginationBaseurl'] = $data['paginationBaseurl'];
}
echo $this->element('/genericElements/IndexTable/pagination', $paginationData);
if (!empty($data['top_bar'])) {
echo $this->element('/genericElements/ListTopBar/scaffold', array('data' => $data['top_bar']));
}
@ -34,17 +39,25 @@
$row_element = $data['row_element'];
}
$rows .= sprintf(
'<tr>%s</tr>',
$this->element('/genericElements/IndexTable/' . $row_element, array('k' => $k, 'row' => $data_row, 'fields' => $data['fields']))
'<tr data-row-id="%s">%s</tr>',
h($k),
$this->element(
'/genericElements/IndexTable/' . $row_element,
array(
'k' => $k,
'row' => $data_row,
'fields' => $data['fields'],
'options' => empty($data['options']) ? array() : $data['options'],
'actions' => empty($data['actions']) ? array() : $data['actions']
)
)
);
}
echo sprintf(
'<table class="table table-striped table-hover table-condensed">%s%s</table>',
$this->element('/genericElements/IndexTable/headers', array('fields' => $data['fields'], 'paginator' => $this->Paginator)),
$this->element('/genericElements/IndexTable/headers', array('fields' => $data['fields'], 'paginator' => $this->Paginator, 'actions' => empty($data['actions']) ? false : true)),
$rows
);
if (empty($data['skip_pagination'])) {
echo $this->element('/genericElements/IndexTable/pagination_counter', array('paginator' => $this->Paginator));
echo $this->element('/genericElements/IndexTable/pagination', array('paginator' => $this->Paginator));
}
echo $this->element('/genericElements/IndexTable/pagination_counter', $paginationData);
echo $this->element('/genericElements/IndexTable/pagination', $paginationData);
?>

View File

@ -1,14 +1,18 @@
<?php
$paginator->options(array(
$options = array(
'update' => '.span12',
'evalScripts' => true,
'before' => '$(".progress").show()',
'complete' => '$(".progress").hide()',
));
sprintf(
);
if (!empty($paginationBaseurl)) {
$options['url'] = $paginationBaseurl;
}
echo $this->Paginator->options($options);
echo sprintf(
'<div class="pagination"><ul>%s%s%s</ul></div>',
$paginator->prev('&laquo; ' . __('previous'), array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'prev disabled', 'escape' => false, 'disabledTag' => 'span')),
$paginator->numbers(array('modulus' => 20, 'separator' => '', 'tag' => 'li', 'currentClass' => 'active', 'currentTag' => 'span')),
$paginator->next(__('next') . ' &raquo;', array('tag' => 'li', 'escape' => false), null, array('tag' => 'li', 'class' => 'next disabled', 'escape' => false, 'disabledTag' => 'span'))
$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'))
);
?>

View File

@ -1,7 +1,7 @@
<?php
echo sprintf(
'<p>%s</p>',
$paginator->counter(array(
$this->Paginator->counter(array(
'format' => __('Page {:page} of {:pages}, showing {:current} records out of {:count} total, starting on record {:start}, ending on {:end}')
))
);

View File

@ -1,20 +1,38 @@
<?php
$rowHtml = '';
foreach ($fields as $k => $field) {
foreach ($fields as $field) {
if (empty($field['element'])) {
$valueField = $this->element('/genericElements/IndexTable/Fields/generic_field', array('field' => $field, 'row' => $row, 'data_path' => empty($field['data_path']) ? '' : $field['data_path']));
$valueField = $this->element('/genericElements/IndexTable/Fields/generic_field', array('field' => $field, 'row' => $row, 'data_path' => empty($field['data_path']) ? '' : $field['data_path'], 'k' => $k));
} else {
$valueField = $this->element('/genericElements/IndexTable/Fields/' . $field['element'], array('field' => $field, 'row' => $row, 'data_path' => empty($field['data_path']) ? '' : $field['data_path']));
$valueField = $this->element(
'/genericElements/IndexTable/Fields/' . $field['element'],
array(
'field' => $field,
'row' => $row,
'data_path' => empty($field['data_path']) ? '' : $field['data_path'], 'k' => $k
)
);
}
$rowHtml .= sprintf(
'<td%s%s%s%s%s>%s</td>',
'<td%s%s%s%s%s%s%s>%s</td>',
(empty($field['id'])) ? '' : sprintf('id="%s"', $field['id']),
(empty($field['class'])) ? '' : sprintf(' class="%s"', $field['class']),
(empty($field['style'])) ? '' : sprintf(' style="%s"', $field['style']),
(empty($field['title'])) ? '' : sprintf(' title="%s"', $field['title']),
(empty($field['name'])) ? '' : sprintf(' data-path="%s"', (h($field['data_path']))),
(empty($field['encode_raw_value']) || empty($field['data_path'])) ? '' : sprintf(' data-value="%s"', (h(Hash::extract($row, $field['data_path'])[0]))),
(empty($field['ondblclick'])) ? '' : sprintf(' ondblclick="%s"', $field['ondblclick']),
$valueField
);
}
if (!empty($actions)) {
$rowHtml .= $this->element(
'/genericElements/IndexTable/Fields/actions',
array(
'actions' => $actions,
'row' => $row
)
);
}
echo ($rowHtml);
?>

View File

@ -587,12 +587,28 @@
'url' => '/servers/add',
'text' => __('New Servers')
));
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'url' => '/communities/index',
'text' => __('List Communities'),
'element_id' => 'list_communities'
));
if ($menuItem === 'view_community' || $menuItem === 'request_community_access') {
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'text' => __('Request Access'),
'url' => '/communities/requestAccesss/' . h($community['community_uuid']),
'element_id' => 'request_community_access'
));
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'text' => __('View community'),
'url' => '/communities/view/' . h($community['community_uuid']),
'element_id' => 'view_community'
));
}
}
break;
case 'admin':
if ($menuItem === 'editUser' || $menuItem === 'viewUser') {
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
'element_id' => 'viewUser',

View File

@ -46,7 +46,7 @@
(empty($row['boolean']) ? 'bold red' : 'bold green') : '',
empty($row['boolean']) ? 'No' : 'Yes'
),
empty($row['value']) ? '' : h($row['value']),
empty($row['value']) ? '' : nl2br(h(trim($row['value']))),
empty($row['html']) ? '' : $row['html'],
empty($element) ? '' : $element
)

View File

@ -252,6 +252,11 @@
'text' => __('Search Feed Caches'),
'url' => '/feeds/searchCaches',
'requirement' => ($isSiteAdmin || $hostOrgUser)
),
array(
'text' => __('List Communities'),
'url' => '/communities/index',
'requirement' => ($isSiteAdmin)
)
)
),

View File

@ -6,6 +6,10 @@ App::uses('AppHelper', 'View/Helper');
*/
class FontAwesomeHelper extends AppHelper {
public function getClass($icon) {
return $this->findNamespace($icon) . ' fa-' . $icon;
}
public function findNamespace($icon)
{
$fab_icons = array(

File diff suppressed because one or more lines are too long

@ -1 +1 @@
Subproject commit 6ca4e4cb1790a56b00c9e9d5b764da1079662a0b
Subproject commit 9926ea88262d06a8155fb2756a53c487f282ba1f

@ -1 +1 @@
Subproject commit 30204266a0ae9d7a9556853cd8f02096396818a0
Subproject commit 69a8ce29165b9e55e137379b2ef7aa42fb598a0c

View File

@ -1626,10 +1626,14 @@ function getPopup(id, context, target, admin, popupType) {
$(popupType).html(data);
openPopup(popupType, false);
},
error:function() {
error:function(xhr) {
$(".loading").hide();
$("#gray_out").fadeOut();
showMessage('fail', 'Something went wrong - the queried function returned an exception. Contact your administrator for further details (the exception has been logged).');
if (xhr.status === 403) {
showMessage('fail', 'Not allowed.');
} else {
showMessage('fail', 'Something went wrong - the queried function returned an exception. Contact your administrator for further details (the exception has been logged).');
}
},
url: url
});