mirror of https://github.com/MISP/MISP
Merge branch 'develop' of github.com:MISP/MISP into feature_workflows/enrichment-improvements
commit
36c4100568
|
@ -1509,9 +1509,17 @@ coreCAKE () {
|
|||
${SUDO_WWW} ${RUN_PHP} -- ${CAKE} Admin setSetting "GnuPG.homedir" "${PATH_TO_MISP}/.gnupg"
|
||||
${SUDO_WWW} ${RUN_PHP} -- ${CAKE} Admin setSetting "GnuPG.password" "${GPG_PASSPHRASE}"
|
||||
${SUDO_WWW} ${RUN_PHP} -- ${CAKE} Admin setSetting "GnuPG.obscure_subject" true
|
||||
${SUDO_WWW} ${RUN_PHP} -- ${CAKE} Admin setSetting "GnuPG.key_fetching_disabled" false
|
||||
# FIXME: what if we have not gpg binary but a gpg2 one?
|
||||
${SUDO_WWW} ${RUN_PHP} -- ${CAKE} Admin setSetting "GnuPG.binary" "$(which gpg)"
|
||||
|
||||
# LinOTP
|
||||
${SUDO_WWW} ${RUN_PHP} -- ${CAKE} Admin setSetting "LinOTPAuth.enabled" false
|
||||
${SUDO_WWW} ${RUN_PHP} -- ${CAKE} Admin setSetting "LinOTPAuth.baseUrl" "https://<your-linotp-baseUrl>"
|
||||
${SUDO_WWW} ${RUN_PHP} -- ${CAKE} Admin setSetting "LinOTPAuth.realm" "lino"
|
||||
${SUDO_WWW} ${RUN_PHP} -- ${CAKE} Admin setSetting "LinOTPAuth.verifyssl" true
|
||||
${SUDO_WWW} ${RUN_PHP} -- ${CAKE} Admin setSetting "LinOTPAuth.mixedauth" false
|
||||
|
||||
# Enable installer org and tune some configurables
|
||||
${SUDO_WWW} ${RUN_PHP} -- ${CAKE} Admin setSetting "MISP.host_org_id" 1
|
||||
${SUDO_WWW} ${RUN_PHP} -- ${CAKE} Admin setSetting "MISP.email" "info@admin.test"
|
||||
|
@ -1870,7 +1878,7 @@ mispmodules () {
|
|||
modulesCAKE () {
|
||||
# Enable Enrichment, set better timeouts
|
||||
${SUDO_WWW} ${RUN_PHP} -- ${CAKE} Admin setSetting "Plugin.Enrichment_services_enable" true
|
||||
${SUDO_WWW} ${RUN_PHP} -- ${CAKE} Admin setSetting "Plugin.Enrichment_hover_enable" true
|
||||
${SUDO_WWW} ${RUN_PHP} -- ${CAKE} Admin setSetting "Plugin.Enrichment_hover_enable" false
|
||||
${SUDO_WWW} ${RUN_PHP} -- ${CAKE} Admin setSetting "Plugin.Enrichment_hover_popover_only" false
|
||||
${SUDO_WWW} ${RUN_PHP} -- ${CAKE} Admin setSetting "Plugin.Enrichment_hover_timeout" 150
|
||||
${SUDO_WWW} ${RUN_PHP} -- ${CAKE} Admin setSetting "Plugin.Enrichment_timeout" 300
|
||||
|
@ -2543,7 +2551,7 @@ apacheConfig_RHEL7 () {
|
|||
#sudo sed -i "s/SetHandler/\#SetHandler/g" /etc/httpd/conf.d/misp.ssl.conf
|
||||
sudo rm /etc/httpd/conf.d/ssl.conf
|
||||
sudo chmod 644 /etc/httpd/conf.d/misp.ssl.conf
|
||||
sudo sed -i '/Listen 80/a Listen 443' /etc/httpd/conf/httpd.conf
|
||||
sudo sed -i '/Listen 443/!s/Listen 80/a Listen 443/' /etc/httpd/conf/httpd.conf
|
||||
|
||||
# If a valid SSL certificate is not already created for the server, create a self-signed certificate:
|
||||
echo "The Common Name used below will be: ${OPENSSL_CN}"
|
||||
|
@ -2591,7 +2599,7 @@ apacheConfig_RHEL8 () {
|
|||
#sudo sed -i "s/SetHandler/\#SetHandler/g" /etc/httpd/conf.d/misp.ssl.conf
|
||||
sudo rm /etc/httpd/conf.d/ssl.conf
|
||||
sudo chmod 644 /etc/httpd/conf.d/misp.ssl.conf
|
||||
sudo sed -i '/Listen 80/a Listen 443' /etc/httpd/conf/httpd.conf
|
||||
sudo sed -i '/Listen 443/!s/Listen 80/a Listen 443/' /etc/httpd/conf/httpd.conf
|
||||
|
||||
# If a valid SSL certificate is not already created for the server, create a self-signed certificate:
|
||||
echo "The Common Name used below will be: ${OPENSSL_CN}"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
; Generated by RHash v1.4.2 on 2022-05-23 at 12:45.34
|
||||
; Generated by RHash v1.4.2 on 2023-07-01 at 17:15.04
|
||||
; Written by Kravchenko Aleksey (Akademgorodok) - http://rhash.sf.net/
|
||||
;
|
||||
; 160126 12:45.34 2022-05-23 INSTALL.sh
|
||||
INSTALL.sh 4296D40B11B3002DF3FDFD69A508ED5ECACB8C13 D32E5A4B0F37F4C937CD4F85927E998D917BCBE89E4E0E864FFD7EA09E29ADEF BD093D8018C351E3D3722646E269C4B60E6DA19F42150338CE6FD72FEE293B8B89AA69D48A84B19D3EFDDAE25EC9E646 ECACC3071E130058C3DDECC86E1CBF27DD4F11389D10F43B14293B1915F7A24F02D0DA51E299706A38C00F2D2A7505B0FE46E33B705E53594383CE65461F2B08
|
||||
; 160686 17:15.04 2023-07-01 INSTALL.sh
|
||||
INSTALL.sh 9576C31EC5BD942E1C9B12413E6408E4623252F7 78B708FE1FC6B39BE081B9F05C6AA5E1478F8762CAF5A8A7671A12EBA4D3C1C5 27991471FB5788F42AF3BBF86FC80A95341AA17AE9487016EEC94961A48437172702EB8E2D6CB300387E87D9E8E0E3E5 C1C21FD491AEFD662C87C3EF62837D769E63E9CF2446B9BD607CCEF8AFD72528824A8F408C6892FD51109390104010EF90DA7F4828950A8671D2986A6B8E216F
|
||||
|
|
|
@ -1 +1 @@
|
|||
4296d40b11b3002df3fdfd69a508ed5ecacb8c13 INSTALL.sh
|
||||
9576c31ec5bd942e1c9b12413e6408e4623252f7 INSTALL.sh
|
||||
|
|
|
@ -1 +1 @@
|
|||
d32e5a4b0f37f4c937cd4f85927e998d917bcbe89e4e0e864ffd7ea09e29adef INSTALL.sh
|
||||
78b708fe1fc6b39be081b9f05c6aa5e1478f8762caf5a8a7671a12eba4d3c1c5 INSTALL.sh
|
||||
|
|
|
@ -1 +1 @@
|
|||
bd093d8018c351e3d3722646e269c4b60e6da19f42150338ce6fd72fee293b8b89aa69d48a84b19d3efddae25ec9e646 INSTALL.sh
|
||||
27991471fb5788f42af3bbf86fc80a95341aa17ae9487016eec94961a48437172702eb8e2d6cb300387e87d9e8e0e3e5 INSTALL.sh
|
||||
|
|
|
@ -1 +1 @@
|
|||
ecacc3071e130058c3ddecc86e1cbf27dd4f11389d10f43b14293b1915f7a24f02d0da51e299706a38c00f2d2a7505b0fe46e33b705e53594383ce65461f2b08 INSTALL.sh
|
||||
c1c21fd491aefd662c87c3ef62837d769e63e9cf2446b9bd607ccef8afd72528824a8f408c6892fd51109390104010ef90da7f4828950a8671d2986a6b8e216f INSTALL.sh
|
||||
|
|
2
PyMISP
2
PyMISP
|
@ -1 +1 @@
|
|||
Subproject commit 7d1d8b6f38f210b28934a206f9c1470542e9da7e
|
||||
Subproject commit ccae32ae716c143bea09954e860238e193bc78c6
|
|
@ -1 +1 @@
|
|||
{"major":2, "minor":4, "hotfix":172}
|
||||
{"major":2, "minor":4, "hotfix":173}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine on
|
||||
RewriteRule ^$ webroot/ [L]
|
||||
RewriteRule (.*) webroot/$1 [L]
|
||||
</IfModule>
|
||||
RewriteRule ^$ webroot/ "[B= ,L]"
|
||||
RewriteRule (.*) webroot/$1 "[B= ,L]"
|
||||
</IfModule>
|
||||
|
|
|
@ -112,6 +112,18 @@ class AdminShell extends AppShell
|
|||
return $parser;
|
||||
}
|
||||
|
||||
public function jobForgot()
|
||||
{
|
||||
if (empty($this->args[0])) {
|
||||
die('Usage: ' . $this->Server->command_line_functions['console_admin_tasks']['data']['Forgot'] . PHP_EOL);
|
||||
}
|
||||
|
||||
$email = $this->args[0];
|
||||
$ip = empty($this->args[1]) ? null : $this->args[1];
|
||||
$jobId = empty($this->args[2]) ? null : $this->args[2];
|
||||
$this->User->forgot($email, $ip, $jobId);
|
||||
}
|
||||
|
||||
public function jobGenerateCorrelation()
|
||||
{
|
||||
if (empty($this->args[0])) {
|
||||
|
|
|
@ -405,7 +405,17 @@ class EventShell extends AppShell
|
|||
$jobId = $this->args[2];
|
||||
$userId = $this->args[3];
|
||||
$user = $this->getUser($userId);
|
||||
$job = $this->Job->read(null, $jobId);
|
||||
$job = $this->Job->find('first', [
|
||||
'recursive' => -1,
|
||||
'conditions' => [
|
||||
'Job.id' => $jobId
|
||||
]
|
||||
]);
|
||||
if (empty($job)) {
|
||||
$log = ClassRegistry::init('Log');
|
||||
$log->createLogEntry($user, 'publish', 'Event', $id, 'Event (' . $id . '): could not be published - valid job not found.', '');
|
||||
return true;
|
||||
}
|
||||
$this->Event->Behaviors->unload('SysLogLogable.SysLogLogable');
|
||||
$result = $this->Event->publish($id, $passAlong);
|
||||
$job['Job']['progress'] = 100;
|
||||
|
|
|
@ -33,8 +33,8 @@ class AppController extends Controller
|
|||
|
||||
public $helpers = array('OrgImg', 'FontAwesome', 'UserName');
|
||||
|
||||
private $__queryVersion = '151';
|
||||
public $pyMispVersion = '2.4.172';
|
||||
private $__queryVersion = '152';
|
||||
public $pyMispVersion = '2.4.173';
|
||||
public $phpmin = '7.2';
|
||||
public $phprec = '7.4';
|
||||
public $phptoonew = '8.0';
|
||||
|
@ -111,6 +111,7 @@ class AppController extends Controller
|
|||
|
||||
$this->_setupBaseurl();
|
||||
$this->Auth->loginRedirect = $this->baseurl . '/users/routeafterlogin';
|
||||
$this->Auth->loginAction = $this->baseurl . '/users/login';
|
||||
|
||||
$customLogout = Configure::read('Plugin.CustomAuth_custom_logout');
|
||||
$this->Auth->logoutRedirect = $customLogout ?: ($this->baseurl . '/users/login');
|
||||
|
@ -222,8 +223,10 @@ class AppController extends Controller
|
|||
!$userLoggedIn &&
|
||||
(
|
||||
$controller !== 'users' ||
|
||||
$action !== 'register' ||
|
||||
empty(Configure::read('Security.allow_self_registration'))
|
||||
(
|
||||
($action !== 'register' || empty(Configure::read('Security.allow_self_registration'))) &&
|
||||
(!in_array($action, ['forgot', 'password_reset']) || empty(Configure::read('Security.allow_password_forgotten')))
|
||||
)
|
||||
)
|
||||
) {
|
||||
// REST authentication
|
||||
|
@ -314,6 +317,10 @@ class AppController extends Controller
|
|||
if (!empty(Configure::read('Security.email_otp_enabled'))) {
|
||||
$preAuthActions[] = 'email_otp';
|
||||
}
|
||||
if (!empty(Configure::read('Security.allow_password_forgotten'))) {
|
||||
$preAuthActions[] = 'forgot';
|
||||
$preAuthActions[] = 'password_reset';
|
||||
}
|
||||
if (!$this->_isControllerAction(['users' => $preAuthActions, 'servers' => ['cspReport']])) {
|
||||
if ($isAjax) {
|
||||
$response = $this->RestResponse->throwException(401, "Unauthorized");
|
||||
|
@ -1112,7 +1119,7 @@ class AppController extends Controller
|
|||
$user['User'] = $temp;
|
||||
if ($user['User']) {
|
||||
$this->User->updateLoginTimes($user['User']);
|
||||
$this->Session->renew();
|
||||
//$this->Session->renew();
|
||||
$this->Session->write(AuthComponent::$sessionKey, $user['User']);
|
||||
if (Configure::read('MISP.log_auth')) {
|
||||
$this->Log = ClassRegistry::init('Log');
|
||||
|
|
|
@ -1539,6 +1539,7 @@ class AttributesController extends AppController
|
|||
$user = $this->Auth->user();
|
||||
$exception = null;
|
||||
$filters = $this->__getSearchFilters($exception);
|
||||
$this->set('passedArgsArray', ['results' => $continue]);
|
||||
if ($this->request->is('post') || !empty($this->request->params['named']['tags'])) {
|
||||
if ($filters === false) {
|
||||
return $exception;
|
||||
|
|
|
@ -613,7 +613,7 @@ class ACLComponent extends Component
|
|||
),
|
||||
'sightings' => array(
|
||||
'add' => array('perm_sighting'),
|
||||
'restSearch' => array('perm_sighting'),
|
||||
'restSearch' => array('*'),
|
||||
'advanced' => array('perm_sighting'),
|
||||
'delete' => ['AND' => ['perm_sighting', 'perm_modify_org']],
|
||||
'index' => array('*'),
|
||||
|
@ -748,6 +748,7 @@ class ACLComponent extends Component
|
|||
'downloadTerms' => array('*'),
|
||||
'edit' => array('self_management_enabled'),
|
||||
'email_otp' => array('*'),
|
||||
'forgot' => array('*'),
|
||||
'otp' => array('*'),
|
||||
'hotp' => array('*'),
|
||||
'totp_new' => array('*'),
|
||||
|
@ -760,6 +761,7 @@ class ACLComponent extends Component
|
|||
'logout' => array('*'),
|
||||
'logout401' => array('*'),
|
||||
'notificationSettings' => ['*'],
|
||||
'password_reset' => array('*'),
|
||||
'register' => array('*'),
|
||||
'registrations' => array(),
|
||||
'resetAllSyncAuthKeys' => array(),
|
||||
|
|
|
@ -192,6 +192,10 @@ class DashboardsController extends AppController
|
|||
'widget_config' => empty($valueConfig['widget_config']) ? array() : $valueConfig['widget_config']
|
||||
);
|
||||
|
||||
if (!empty($this->request->params['named']['exportjson'])) {
|
||||
return $this->RestResponse->viewData($data);
|
||||
}
|
||||
|
||||
$this->layout = false;
|
||||
$this->set('title', $dashboardWidget->title);
|
||||
$this->set('widget_id', $widget_id);
|
||||
|
|
|
@ -38,7 +38,7 @@ class GalaxyClustersController extends AppController
|
|||
public function index($galaxyId)
|
||||
{
|
||||
$galaxyId = $this->Toolbox->findIdByUuid($this->GalaxyCluster->Galaxy, $galaxyId);
|
||||
$filters = $this->IndexFilter->harvestParameters(array('context', 'searchall'));
|
||||
$filters = $this->_harvestParameters(array('context', 'searchall'));
|
||||
$aclConditions = $this->GalaxyCluster->buildConditions($this->Auth->user());
|
||||
$contextConditions = array();
|
||||
if (empty($filters['context'])) {
|
||||
|
|
|
@ -915,30 +915,52 @@ class ServersController extends AppController
|
|||
App::uses('File', 'Utility');
|
||||
App::uses('Folder', 'Utility');
|
||||
App::uses('FileAccessTool', 'Tools');
|
||||
App::uses('SyncTool', 'Tools');
|
||||
if (isset($server['Server'][$subm]['name'])) {
|
||||
if ($this->request->data['Server'][$subm]['size'] != 0) {
|
||||
if (!$this->Server->checkFilename($server['Server'][$subm]['name'])) {
|
||||
throw new Exception(__('Filename not allowed'));
|
||||
}
|
||||
$file = new File($server['Server'][$subm]['name']);
|
||||
$ext = $file->ext();
|
||||
|
||||
if (!is_uploaded_file($server['Server'][$subm]['tmp_name'])) {
|
||||
throw new Exception(__('File not uploaded correctly'));
|
||||
}
|
||||
|
||||
$ext = pathinfo($server['Server'][$subm]['name'], PATHINFO_EXTENSION);
|
||||
if (!in_array($ext, SyncTool::ALLOWED_CERT_FILE_EXTENSIONS)) {
|
||||
$this->Flash->error(__('Invalid extension.'));
|
||||
$this->redirect(array('action' => 'index'));
|
||||
}
|
||||
|
||||
if (!$server['Server'][$subm]['size'] > 0) {
|
||||
$this->Flash->error(__('Incorrect extension or empty file.'));
|
||||
$this->redirect(array('action' => 'index'));
|
||||
}
|
||||
|
||||
// read pem file data
|
||||
$pemData = FileAccessTool::readFromFile($server['Server'][$subm]['tmp_name'], $server['Server'][$subm]['size']);
|
||||
// read certificate file data
|
||||
$certData = FileAccessTool::readFromFile($server['Server'][$subm]['tmp_name'], $server['Server'][$subm]['size']);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
$pemData = base64_decode($server['Server'][$subm]);
|
||||
$ext = 'pem';
|
||||
$certData = base64_decode($server['Server'][$subm]);
|
||||
}
|
||||
|
||||
// check if the file is a valid x509 certificate
|
||||
try {
|
||||
$cert = openssl_x509_parse($certData);
|
||||
if (!$cert) {
|
||||
throw new Exception(__('Invalid certificate.'));
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$this->Flash->error(__('Invalid certificate.'));
|
||||
$this->redirect(array('action' => 'index'));
|
||||
}
|
||||
|
||||
$destpath = APP . "files" . DS . "certs" . DS;
|
||||
$dir = new Folder(APP . "files" . DS . "certs", true);
|
||||
$pemfile = new File($destpath . $id . $ins . '.' . $ext);
|
||||
$result = $pemfile->write($pemData);
|
||||
$result = $pemfile->write($certData);
|
||||
$s = $this->Server->read(null, $id);
|
||||
$s['Server'][$attr] = $s['Server']['id'] . $ins . '.' . $ext;
|
||||
if ($result) {
|
||||
|
|
|
@ -78,7 +78,7 @@ class ShadowAttributesController extends AppController
|
|||
}
|
||||
|
||||
if (isset($shadow['proposal_to_delete']) && $shadow['proposal_to_delete']) {
|
||||
$this->Attribute->delete($activeAttribute['Attribute']['id']);
|
||||
$this->Attribute->deleteAttribute($activeAttribute['Attribute']['id'], $this->Auth->user(), false);
|
||||
} else {
|
||||
// Update the live attribute with the shadow data
|
||||
$fieldsToUpdate = array('value1', 'value2', 'value', 'type', 'category', 'comment', 'to_ids', 'first_seen', 'last_seen');
|
||||
|
@ -906,7 +906,24 @@ class ShadowAttributesController extends AppController
|
|||
}
|
||||
$params = array(
|
||||
'conditions' => $conditions,
|
||||
'fields' => array('ShadowAttribute.id', 'ShadowAttribute.old_id', 'ShadowAttribute.event_id', 'ShadowAttribute.type', 'ShadowAttribute.category', 'ShadowAttribute.uuid', 'ShadowAttribute.to_ids', 'ShadowAttribute.value', 'ShadowAttribute.comment', 'ShadowAttribute.org_id', 'ShadowAttribute.timestamp', 'ShadowAttribute.first_seen', 'ShadowAttribute.last_seen'),
|
||||
'fields' => array(
|
||||
'ShadowAttribute.id',
|
||||
'ShadowAttribute.old_id',
|
||||
'ShadowAttribute.event_id',
|
||||
'ShadowAttribute.type',
|
||||
'ShadowAttribute.category',
|
||||
'ShadowAttribute.uuid',
|
||||
'ShadowAttribute.to_ids',
|
||||
'ShadowAttribute.value',
|
||||
'ShadowAttribute.comment',
|
||||
'ShadowAttribute.org_id',
|
||||
'ShadowAttribute.timestamp',
|
||||
'ShadowAttribute.first_seen',
|
||||
'ShadowAttribute.last_seen',
|
||||
'ShadowAttribute.deleted',
|
||||
'ShadowAttribute.proposal_to_delete',
|
||||
'ShadowAttribute.disable_correlation'
|
||||
),
|
||||
'contain' => array(
|
||||
'Event' => array(
|
||||
'fields' => array('id', 'org_id', 'info', 'orgc_id', 'uuid'),
|
||||
|
|
|
@ -66,7 +66,8 @@ class SightingsController extends AppController
|
|||
$filters = !empty($this->request->data['filters']) ? $this->request->data['filters'] : false;
|
||||
}
|
||||
if (!$error) {
|
||||
$result = $this->Sighting->saveSightings($id, $values, $timestamp, $this->Auth->user(), $type, $source, false, true, false, $filters);
|
||||
$publish_sighting = !empty(Configure::read('Sightings_enable_realtime_publish'));
|
||||
$result = $this->Sighting->saveSightings($id, $values, $timestamp, $this->Auth->user(), $type, $source, false, $publish_sighting, false, $filters);
|
||||
}
|
||||
if (!is_numeric($result)) {
|
||||
$error = $result;
|
||||
|
|
|
@ -30,6 +30,10 @@ class UsersController extends AppController
|
|||
|
||||
// what pages are allowed for non-logged-in users
|
||||
$allowedActions = array('login', 'logout', 'getGpgPublicKey', 'logout401', 'otp');
|
||||
if (!empty(Configure::read('Security.allow_password_forgotten'))) {
|
||||
$allowedActions[] = 'forgot';
|
||||
$allowedActions[] = 'password_reset';
|
||||
}
|
||||
if(!empty(Configure::read('Security.email_otp_enabled'))) {
|
||||
$allowedActions[] = 'email_otp';
|
||||
}
|
||||
|
@ -262,6 +266,77 @@ class UsersController extends AppController
|
|||
$this->set('canFetchPgpKey', $this->__canFetchPgpKey());
|
||||
}
|
||||
|
||||
private function __pw_change($user, $source, &$abortPost, $token = false)
|
||||
{
|
||||
if (!isset($this->request->data['User'])) {
|
||||
$this->request->data = array('User' => $this->request->data);
|
||||
}
|
||||
if (Configure::read('Security.require_password_confirmation')) {
|
||||
if (!empty($this->request->data['User']['current_password'])) {
|
||||
$hashed = $this->User->verifyPassword($this->Auth->user('id'), $this->request->data['User']['current_password']);
|
||||
if (!$hashed) {
|
||||
$message = __('Invalid password. Please enter your current password to continue.');
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveFailResponse('Users', $source, false, $message, $this->response->type());
|
||||
}
|
||||
$abortPost = true;
|
||||
$this->Flash->error($message);
|
||||
}
|
||||
unset($this->request->data['User']['current_password']);
|
||||
} else if (!$this->_isRest()) {
|
||||
$message = __('Please enter your current password to continue.');
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveFailResponse('Users', $source, false, $message, $this->response->type());
|
||||
}
|
||||
$abortPost = true;
|
||||
$this->Flash->info($message);
|
||||
}
|
||||
}
|
||||
$hashed = $this->User->verifyPassword($this->Auth->user('id'), $this->request->data['User']['password']);
|
||||
if ($hashed) {
|
||||
$message = __('Submitted new password cannot be the same as the current one');
|
||||
$abortPost = true;
|
||||
}
|
||||
if (!$abortPost) {
|
||||
// What fields should be saved (allowed to be saved)
|
||||
$user['User']['change_pw'] = 0;
|
||||
$user['User']['password'] = $this->request->data['User']['password'];
|
||||
if ($this->_isRest()) {
|
||||
$user['User']['confirm_password'] = $this->request->data['User']['password'];
|
||||
} else {
|
||||
$user['User']['confirm_password'] = $this->request->data['User']['confirm_password'];
|
||||
}
|
||||
$temp = $user['User']['password'];
|
||||
// Save the data
|
||||
if ($this->User->save($user)) {
|
||||
if ($token) {
|
||||
$this->User->purgeForgetToken($token);
|
||||
}
|
||||
$message = __('Password Changed.');
|
||||
// log as System if the reset comes from an unauthed user using password_reset tokens
|
||||
$logUser = empty($this->Auth->user()) ? 'SYSTEM' : $this->Auth->user();
|
||||
$this->User->extralog($logUser, $source, null, null, $user);
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveSuccessResponse('User', $source, false, $this->response->type(), $message);
|
||||
}
|
||||
$this->Flash->success($message);
|
||||
$this->redirect(array('action' => 'view', $user['User']['id']));
|
||||
} else {
|
||||
$message = __('The password could not be updated. Make sure you meet the minimum password length / complexity requirements.');
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveFailResponse('Users', $source, false, $message, $this->response->type());
|
||||
}
|
||||
$this->Flash->error($message);
|
||||
}
|
||||
} else {
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveFailResponse('Users', $source, false, $message, $this->response->type());
|
||||
} else {
|
||||
$this->Flash->error($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function change_pw()
|
||||
{
|
||||
$id = $this->Auth->user('id');
|
||||
|
@ -270,69 +345,8 @@ class UsersController extends AppController
|
|||
'recursive' => -1
|
||||
));
|
||||
if ($this->request->is('post') || $this->request->is('put')) {
|
||||
if (!isset($this->request->data['User'])) {
|
||||
$this->request->data = array('User' => $this->request->data);
|
||||
}
|
||||
$abortPost = false;
|
||||
if (Configure::read('Security.require_password_confirmation')) {
|
||||
if (!empty($this->request->data['User']['current_password'])) {
|
||||
$hashed = $this->User->verifyPassword($this->Auth->user('id'), $this->request->data['User']['current_password']);
|
||||
if (!$hashed) {
|
||||
$message = __('Invalid password. Please enter your current password to continue.');
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveFailResponse('Users', 'change_pw', false, $message, $this->response->type());
|
||||
}
|
||||
$abortPost = true;
|
||||
$this->Flash->error($message);
|
||||
}
|
||||
unset($this->request->data['User']['current_password']);
|
||||
} else if (!$this->_isRest()) {
|
||||
$message = __('Please enter your current password to continue.');
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveFailResponse('Users', 'change_pw', false, $message, $this->response->type());
|
||||
}
|
||||
$abortPost = true;
|
||||
$this->Flash->info($message);
|
||||
}
|
||||
}
|
||||
$hashed = $this->User->verifyPassword($this->Auth->user('id'), $this->request->data['User']['password']);
|
||||
if ($hashed) {
|
||||
$message = __('Submitted new password cannot be the same as the current one');
|
||||
$abortPost = true;
|
||||
}
|
||||
if (!$abortPost) {
|
||||
// What fields should be saved (allowed to be saved)
|
||||
$user['User']['change_pw'] = 0;
|
||||
$user['User']['password'] = $this->request->data['User']['password'];
|
||||
if ($this->_isRest()) {
|
||||
$user['User']['confirm_password'] = $this->request->data['User']['password'];
|
||||
} else {
|
||||
$user['User']['confirm_password'] = $this->request->data['User']['confirm_password'];
|
||||
}
|
||||
$temp = $user['User']['password'];
|
||||
// Save the data
|
||||
if ($this->User->save($user)) {
|
||||
$message = __('Password Changed.');
|
||||
$this->User->extralog($this->Auth->user(), "change_pw", null, null, $user);
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveSuccessResponse('User', 'change_pw', false, $this->response->type(), $message);
|
||||
}
|
||||
$this->Flash->success($message);
|
||||
$this->redirect(array('action' => 'view', $id));
|
||||
} else {
|
||||
$message = __('The password could not be updated. Make sure you meet the minimum password length / complexity requirements.');
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveFailResponse('Users', 'change_pw', false, $message, $this->response->type());
|
||||
}
|
||||
$this->Flash->error($message);
|
||||
}
|
||||
} else {
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveFailResponse('Users', 'change_pw', false, $message, $this->response->type());
|
||||
} else {
|
||||
$this->Flash->error($message);
|
||||
}
|
||||
}
|
||||
return $this->__pw_change($user, 'change_pw', $abortPost);
|
||||
}
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->describe('Users', 'change_pw', false, $this->response->type());
|
||||
|
@ -1369,6 +1383,7 @@ class UsersController extends AppController
|
|||
unset($user['User']['password']);
|
||||
$user['User']['action'] = 'logout';
|
||||
$this->User->save($user['User'], true, array('id'));
|
||||
$this->Session->write('otp_secret', null);
|
||||
$this->redirect($this->Auth->logout());
|
||||
}
|
||||
|
||||
|
@ -1878,7 +1893,11 @@ class UsersController extends AppController
|
|||
);
|
||||
$writer = new \BaconQrCode\Writer($renderer);
|
||||
$totp->setLabel($user['User']['email']);
|
||||
$totp->setIssuer(Configure::read('MISP.org') . ' MISP');
|
||||
if (Configure::read('Security.otp_issuer')) {
|
||||
$totp->setIssuer(Configure::read('Security.otp_issuer'));
|
||||
} else {
|
||||
$totp->setIssuer(Configure::read('MISP.org') . ' MISP');
|
||||
}
|
||||
$qrcode = $writer->writeString($totp->getProvisioningUri());
|
||||
$qrcode = preg_replace('/^.+\n/', '', $qrcode); // ignore first <?xml version line
|
||||
|
||||
|
@ -3080,4 +3099,69 @@ class UsersController extends AppController
|
|||
# To use this, set Plugin.CustomAuth_custom_logout to /users/logout401
|
||||
$this->response->statusCode(401);
|
||||
}
|
||||
|
||||
public function forgot()
|
||||
{
|
||||
if (empty(Configure::read('Security.allow_password_forgotten'))) {
|
||||
$this->Flash->error(__('This feature is disabled.'));
|
||||
$this->redirect('/');
|
||||
}
|
||||
if (!empty($this->Auth->user()) && !$this->_isRest()) {
|
||||
$this->Flash->info(__('You are already logged in, no need to ask for a password reset. Log out first.'));
|
||||
$this->redirect('/');
|
||||
}
|
||||
if ($this->request->is('post')) {
|
||||
if (empty($this->request->data['User'])) {
|
||||
$this->request->data = ['User' => $this->request->data];
|
||||
}
|
||||
if (empty($this->request->data['User']['email'])) {
|
||||
throw new MethodNotAllowedException(__('No email provided, cannot generate password reset message.'));
|
||||
}
|
||||
$user = [
|
||||
'id' => 0,
|
||||
'email' => 'SYSTEM',
|
||||
'Organisation' => [
|
||||
'name' => 'SYSTEM'
|
||||
]
|
||||
];
|
||||
$this->loadModel('Log');
|
||||
$this->Log->createLogEntry($user, 'forgot', 'User', 0, 'Password reset requested for: ' . $this->request->data['User']['email']);
|
||||
$this->User->forgotRouter($this->request->data['User']['email'], $this->_remoteIp());
|
||||
$message = __('Password reset request submitted. If a valid user is found, you should receive an e-mail with a temporary reset link momentarily. Please be advised that this link is only valid for 10 minutes.');
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveSuccessResponse('User', 'forgot', false, $this->response->type(), $message);
|
||||
}
|
||||
$this->Flash->info($message);
|
||||
$this->redirect('/');
|
||||
}
|
||||
}
|
||||
|
||||
public function password_reset($token)
|
||||
{
|
||||
if (empty(Configure::read('Security.allow_password_forgotten'))) {
|
||||
$this->Flash->error(__('This feature is disabled.'));
|
||||
$this->redirect('/');
|
||||
}
|
||||
$this->loadModel('Server');
|
||||
$this->set('complexity', !empty(Configure::read('Security.password_policy_complexity')) ? Configure::read('Security.password_policy_complexity') : $this->Server->serverSettings['Security']['password_policy_complexity']['value']);
|
||||
$this->set('length', !empty(Configure::read('Security.password_policy_length')) ? Configure::read('Security.password_policy_length') : $this->Server->serverSettings['Security']['password_policy_length']['value']);
|
||||
if (!empty($this->Auth->user()) && !$this->_isRest()) {
|
||||
$this->redirect('/');
|
||||
}
|
||||
$user = $this->User->fetchForgottenPasswordUser($token);
|
||||
if (empty($user)) {
|
||||
$message = __('Invalid token, or password request token already expired.');
|
||||
if ($this->_isRest()) {
|
||||
throw new MethodNotAllowedException($message);
|
||||
} else {
|
||||
$this->Flash->error($message);
|
||||
$this->redirect('/');
|
||||
}
|
||||
}
|
||||
if ($this->request->is('post') || $this->request->is('put')) {
|
||||
$abortPost = false;
|
||||
return $this->__pw_change(['User' => $user], 'password_reset', $abortPost, $token);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ class APIActivityWidget
|
|||
'limit' => 'Limits the number of displayed APIkeys. (-1 will list all) Default: -1',
|
||||
'days' => 'How many days back should the list go - for example, setting 7 will only show contributions in the past 7 days. (integer)',
|
||||
'month' => 'Who contributed most this month? (boolean)',
|
||||
'previous_month' => 'Who contributed most the previous, finished month? (boolean)',
|
||||
'year' => 'Which contributed most this year? (boolean)',
|
||||
];
|
||||
public $description = 'Basic widget showing some server statistics in regards to MISP.';
|
||||
|
@ -26,16 +27,20 @@ class APIActivityWidget
|
|||
$begin = new DateTime(date('Y-m-d', strtotime(sprintf("-%s days", $options['days']))));
|
||||
} else if (!empty($options['month'])) {
|
||||
$begin = new DateTime(date('Y-m-d', strtotime('first day of this month 00:00:00', time())));
|
||||
} else if (!empty($options['previous_month'])) {
|
||||
$begin = new DateTime(date('Y-m-d', strtotime('first day of last month 00:00:00', time())));
|
||||
$end = new DateTime(date('Y-m-d', strtotime('last day of last month 23:59:59', time())));
|
||||
} else if (!empty($options['year'])) {
|
||||
$begin = new DateTime(date('Y-m-d', strtotime('first day of this year 00:00:00', time())));
|
||||
} else {
|
||||
$begin = new DateTime(date('Y-m-d', strtotime('-7 days', time())));;
|
||||
}
|
||||
$now = new DateTime();
|
||||
|
||||
$end = isset($end) ? $end : new DateTime();
|
||||
$dates = new DatePeriod(
|
||||
$begin,
|
||||
new DateInterval('P1D'),
|
||||
$now
|
||||
$end
|
||||
);
|
||||
$results = [];
|
||||
foreach ($dates as $date) {
|
||||
|
@ -87,6 +92,7 @@ class APIActivityWidget
|
|||
'recursive' => 1
|
||||
]);
|
||||
}
|
||||
$results = [];
|
||||
$baseurl = empty(Configure::read('MISP.external_baseurl')) ? h(Configure::read('MISP.baseurl')) : Configure::read('MISP.external_baseurl');
|
||||
foreach ($counts as $key => $junk) {
|
||||
$data = $temp_apikeys[$key];
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
class AttackWidget
|
||||
{
|
||||
public $title = 'ATT&CK heatmap';
|
||||
public $render = 'Attack';
|
||||
public $description = 'Retrieve an ATT&CK (or ATT&CK like) heatmap for the current instance.';
|
||||
public $width = 3;
|
||||
public $height = 4;
|
||||
public $params = [
|
||||
'filters' => 'A list of restsearch filters to apply to the heatmap. (dictionary, prepending values with ! uses them as a negation)'
|
||||
];
|
||||
public $cacheLifetime = 1200;
|
||||
public $autoRefreshDelay = false;
|
||||
private $validFilterKeys = [
|
||||
'filters'
|
||||
];
|
||||
private $Event = null;
|
||||
public $placeholder =
|
||||
'{
|
||||
"filters": {
|
||||
"attackGalaxy": "mitre-attack-pattern",
|
||||
"timestamp": ["2023-01-01", "2023-03-31"],
|
||||
"published": [0,1]
|
||||
}
|
||||
}';
|
||||
|
||||
public function handler($user, $options = array())
|
||||
{
|
||||
$this->Event = ClassRegistry::init('Event');
|
||||
$data = null;
|
||||
if (!empty($options['filters'])) {
|
||||
$data = $this->Event->restSearch($user, 'attack', $options['filters']);
|
||||
$data = JsonTool::decode($data->intoString());
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -11,6 +11,7 @@ class LoginsWidget
|
|||
'limit' => 'Limits the number of displayed APIkeys. (-1 will list all) Default: -1',
|
||||
'days' => 'How many days back should the list go - for example, setting 7 will only show contributions in the past 7 days. (integer)',
|
||||
'month' => 'Who contributed most this month? (boolean)',
|
||||
'previous_month' => 'Who contributed most the previous, finished month? (boolean)',
|
||||
'year' => 'Which contributed most this year? (boolean)',
|
||||
];
|
||||
public $description = 'Basic widget showing some server statistics in regards to MISP.';
|
||||
|
@ -26,12 +27,22 @@ class LoginsWidget
|
|||
$begin = date('Y-m-d H:i:s', strtotime(sprintf("-%s days", $options['days'])));
|
||||
} else if (!empty($options['month'])) {
|
||||
$begin = date('Y-m-d H:i:s', strtotime('first day of this month 00:00:00', time()));
|
||||
} else if (!empty($options['previous_month'])) {
|
||||
$begin = date('Y-m-d H:i:s', strtotime('first day of last month 00:00:00', time()));
|
||||
$end = date('Y-m-d H:i:s', strtotime('last day of last month 23:59:59', time()));
|
||||
} else if (!empty($options['year'])) {
|
||||
$begin = date('Y-m-d', strtotime('first day of this year 00:00:00', time()));
|
||||
} else {
|
||||
$begin = date('Y-m-d H:i:s', strtotime('-7 days', time()));
|
||||
}
|
||||
return $begin ? ['Log.created >=' => $begin] : [];
|
||||
$params = [];
|
||||
if (!empty($end)) {
|
||||
$params['Log.created <='] = $end;
|
||||
}
|
||||
if (!empty($begin)) {
|
||||
$params['Log.created >='] = $begin;
|
||||
}
|
||||
return $params;
|
||||
}
|
||||
|
||||
public function handler($user, $options = array())
|
||||
|
|
|
@ -15,6 +15,7 @@ class NewOrgsWidget
|
|||
'filter' => 'A list of filters by organisation meta information (nationality, sector, type, name, uuid) to include. (dictionary, prepending values with ! uses them as a negation)',
|
||||
'days' => 'How many days back should the list go - for example, setting 7 will only show the organisations that were added in the past 7 days. (integer)',
|
||||
'month' => 'Which organisations have been added this month? (boolean)',
|
||||
'previous_month' => 'Who contributed most the previous, finished month? (boolean)',
|
||||
'year' => 'Which organisations have been added this year? (boolean)',
|
||||
'local' => 'Should the list only show local organisations? (boolean or list of booleans, defaults to 1. To get both sets, use [0,1])',
|
||||
'fields' => 'Which fields should be displayed, by default all are selected. Pass a list with the following options: [id, uuid, name, sector, type, nationality, creation_date]'
|
||||
|
@ -51,6 +52,10 @@ class NewOrgsWidget
|
|||
} else if (!empty($options['month'])) {
|
||||
$condition = strtotime('first day of this month 00:00:00', time());
|
||||
$this->tableDescription = __('The %d newest organisations created during the current month', $limit);
|
||||
} else if (!empty($options['previous_month'])) {
|
||||
$condition = strtotime('first day of last month 00:00:00', time());
|
||||
$end_condition = strtotime('last day of last month 23:59:59', time());
|
||||
$this->tableDescription = __('The %d newest organisations created during the previous month', $limit);
|
||||
} else if (!empty($options['year'])) {
|
||||
$condition = strtotime('first day of this year 00:00:00', time());
|
||||
$this->tableDescription = __('The %d newest organisations created during the current year', $limit);
|
||||
|
@ -58,9 +63,18 @@ class NewOrgsWidget
|
|||
$this->tableDescription = __('The %d newest organisations created', $limit);
|
||||
return null;
|
||||
}
|
||||
$datetime = new DateTime();
|
||||
$datetime->setTimestamp($condition);
|
||||
return $datetime->format('Y-m-d H:i:s');
|
||||
$conditions = [];
|
||||
if (!empty($condition)) {
|
||||
$datetime = new DateTime();
|
||||
$datetime->setTimestamp($condition);
|
||||
$conditions['Organisation.date_created >='] = $datetime->format('Y-m-d H:i:s');
|
||||
}
|
||||
if (!empty($end_condition)) {
|
||||
$datetime = new DateTime();
|
||||
$datetime->setTimestamp($end_condition);
|
||||
$conditions['Organisation.date_created <='] = $datetime->format('Y-m-d H:i:s');
|
||||
}
|
||||
return $conditions;
|
||||
}
|
||||
|
||||
public function handler($user, $options = array())
|
||||
|
|
|
@ -15,6 +15,7 @@ class NewUsersWidget
|
|||
'filter' => 'A list of filters for the organisations (nationality, sector, type, name, uuid) to include. (dictionary, prepending values with ! uses them as a negation)',
|
||||
'days' => 'How many days back should the list go - for example, setting 7 will only show the organisations that were added in the past 7 days. (integer)',
|
||||
'month' => 'Which organisations have been added this month? (boolean)',
|
||||
'previous_month' => 'Who contributed most the previous, finished month? (boolean)',
|
||||
'year' => 'Which organisations have been added this year? (boolean)',
|
||||
'fields' => 'Which fields should be displayed, by default all are selected. Pass a list with the following options: [id, email, Organisation.name, Role.name, date_created]'
|
||||
];
|
||||
|
@ -57,6 +58,10 @@ class NewUsersWidget
|
|||
} else if (!empty($options['month'])) {
|
||||
$condition = strtotime('first day of this month 00:00:00', time());
|
||||
$this->tableDescription = __('The %d newest users created during the current month', $limit);
|
||||
} else if (!empty($options['previous_month'])) {
|
||||
$condition = strtotime('first day of last month 00:00:00', time());
|
||||
$end_condition = strtotime('last day of last month 23:59:59', time());
|
||||
$this->tableDescription = __('The %d newest organisations created during the previous month', $limit);
|
||||
} else if (!empty($options['year'])) {
|
||||
$condition = strtotime('first day of this year 00:00:00', time());
|
||||
$this->tableDescription = __('The %d newest users created during the current year', $limit);
|
||||
|
@ -64,7 +69,18 @@ class NewUsersWidget
|
|||
$this->tableDescription = __('The %d newest users created', $limit);
|
||||
return null;
|
||||
}
|
||||
return $condition;
|
||||
$conditions = [];
|
||||
if (!empty($condition)) {
|
||||
$datetime = new DateTime();
|
||||
$datetime->setTimestamp($condition);
|
||||
$conditions['Organisation.date_created >='] = $datetime->format('Y-m-d H:i:s');
|
||||
}
|
||||
if (!empty($end_condition)) {
|
||||
$datetime = new DateTime();
|
||||
$datetime->setTimestamp($end_condition);
|
||||
$conditions['Organisation.date_created <='] = $datetime->format('Y-m-d H:i:s');
|
||||
}
|
||||
return $conditions;
|
||||
}
|
||||
|
||||
public function handler($user, $options = array())
|
||||
|
@ -123,7 +139,7 @@ class NewUsersWidget
|
|||
}
|
||||
$timeConditions = $this->timeConditions($options);
|
||||
if ($timeConditions) {
|
||||
$params['conditions']['AND'][] = ['User.date_created >=' => $timeConditions];
|
||||
$params['conditions']['AND'][] = $timeConditions;
|
||||
}
|
||||
if (isset($options['fields'])) {
|
||||
$fields = [];
|
||||
|
|
|
@ -9,6 +9,7 @@ class OrgContributionToplistWidget
|
|||
public $params = [
|
||||
'days' => 'How many days back should the list go - for example, setting 7 will only show contributions in the past 7 days. (integer)',
|
||||
'month' => 'Who contributed most this month? (boolean)',
|
||||
'previous_month' => 'Who contributed most the previous, finished month? (boolean)',
|
||||
'year' => 'Which contributed most this year? (boolean)',
|
||||
'filter' => 'A list of filters by organisation meta information (nationality, sector, type, name, uuid, local (- expects a boolean or a list of boolean values)) to include. (dictionary, prepending values with ! uses them as a negation)',
|
||||
'limit' => 'Limits the number of displayed tags. Default: 10'
|
||||
|
@ -41,12 +42,26 @@ class OrgContributionToplistWidget
|
|||
$condition = strtotime(sprintf("-%s days", $options['days']));
|
||||
} else if (!empty($options['month'])) {
|
||||
$condition = strtotime('first day of this month 00:00:00', time());
|
||||
} else if (!empty($options['previous_month'])) {
|
||||
$condition = strtotime('first day of previous month 00:00:00', time());
|
||||
$end_condition = strtotime('last day of last month 23:59:59', time());
|
||||
} else if (!empty($options['year'])) {
|
||||
$condition = strtotime('first day of this year 00:00:00', time());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return $condition;
|
||||
$conditions = [];
|
||||
if (!empty($condition)) {
|
||||
$datetime = new DateTime();
|
||||
$datetime->setTimestamp($condition);
|
||||
$conditions['Event.timestamp >='] = $datetime->format('Y-m-d H:i:s');
|
||||
}
|
||||
if (!empty($end_condition)) {
|
||||
$datetime = new DateTime();
|
||||
$datetime->setTimestamp($end_condition);
|
||||
$conditions['Event.timestamp <='] = $datetime->format('Y-m-d H:i:s');
|
||||
}
|
||||
return $conditions;
|
||||
}
|
||||
|
||||
|
||||
|
@ -55,7 +70,7 @@ class OrgContributionToplistWidget
|
|||
$params = ['conditions' => []];
|
||||
$timeConditions = $this->timeConditions($options);
|
||||
if ($timeConditions) {
|
||||
$params['conditions']['AND'][] = ['Event.timestamp >=' => $timeConditions];
|
||||
$params['conditions']['AND'][] = $timeConditions;
|
||||
}
|
||||
if (!empty($options['filter']) && is_array($options['filter'])) {
|
||||
foreach ($this->validFilterKeys as $filterKey) {
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
<?php
|
||||
/**
|
||||
* Org Events widget which reportes the number of events created monthly by each local organizations
|
||||
*
|
||||
*/
|
||||
class OrgEventsWidget
|
||||
{
|
||||
public $title = 'Org Events';
|
||||
public $render = 'MultiLineChart';
|
||||
public $width = 8;
|
||||
public $height = 6;
|
||||
public $description = 'A graph to show the monthly number of events per organisation';
|
||||
public $cacheLifetime = 10;
|
||||
public $autoRefreshDelay = false;
|
||||
public $params = array (
|
||||
'blocklist_orgs' => 'A list of organisation names to filter out',
|
||||
'months' => 'Number of past months to consider for the graph',
|
||||
'logarithmic' => 'Visualize data on logarithmic scale'
|
||||
);
|
||||
|
||||
public $placeholder =
|
||||
'{
|
||||
"blocklist_orgs": ["Orgs to filter"],
|
||||
"months": "6",
|
||||
"logarithmic": "true"
|
||||
}';
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Target_month must be from 1 to 12
|
||||
* Target year must be 4 digits
|
||||
*/
|
||||
private function org_events_count($user, $org, $target_month, $target_year) {
|
||||
$events_count = 0;
|
||||
|
||||
$start_date = $target_year.'-'.$target_month.'-01';
|
||||
if($target_month == 12) {
|
||||
$end_date = ($target_year+1).'-01-01';
|
||||
} else {
|
||||
$end_date = $target_year.'-'.($target_month+1).'-01';
|
||||
}
|
||||
$conditions = array('Event.orgc_id' => $org['Organisation']['id'], 'Event.date >=' => $start_date, 'Event.date <' => $end_date);
|
||||
|
||||
//This is required to enforce the ACL (not pull directly from the DB)
|
||||
$eventIds = $this->Event->fetchSimpleEventIds($user, array('conditions' => $conditions));
|
||||
|
||||
if(!empty($eventIds)) {
|
||||
$params = array('Event.id' => $eventIds);
|
||||
$events = $this->Event->find('all', array('conditions' => array('AND' => $params)));
|
||||
foreach($events as $event) {
|
||||
$events_count+= 1;
|
||||
}
|
||||
}
|
||||
return $events_count;
|
||||
}
|
||||
|
||||
private function filter_ghost_orgs(&$data, $orgs){
|
||||
foreach ($data['data'] as &$item) {
|
||||
foreach(array_keys($orgs) as $org_name) {
|
||||
unset($item[$org_name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function handler($user, $options = array())
|
||||
{
|
||||
$this->Log = ClassRegistry::init('Log');
|
||||
$this->Org = ClassRegistry::init('Organisation');
|
||||
$this->Event = ClassRegistry::init('Event');
|
||||
$orgs = $this->Org->find('all', array( 'conditions' => array('Organisation.local' => 1)));
|
||||
$current_month = date('n');
|
||||
$current_year = date('Y');
|
||||
$limit = 6; // months
|
||||
if(!empty($options['months'])) {
|
||||
$limit = (int) ($options['months']);
|
||||
}
|
||||
$offset = 0;
|
||||
$ghost_orgs = array(); // track orgs without any contribution
|
||||
// We start by putting all orgs_id in there:
|
||||
foreach($orgs as $org) {
|
||||
// We check for blocklisted orgs
|
||||
if(!empty($options['blocklist_orgs']) && in_array($org['Organisation']['name'], $options['blocklist_orgs'])) {
|
||||
unset($orgs[$offset]);
|
||||
} else {
|
||||
$ghost_orgs[$org['Organisation']['name']] = true;
|
||||
}
|
||||
$offset++;
|
||||
}
|
||||
$data = array();
|
||||
$data['data'] = array();
|
||||
for ($i=0; $i < $limit; $i++) {
|
||||
$target_month = $current_month - $i;
|
||||
$target_year = $current_year;
|
||||
if ($target_month < 1) {
|
||||
$target_month += 12;
|
||||
$target_year -= 1;
|
||||
}
|
||||
$item = array();
|
||||
$item ['date'] = $target_year.'-'.$target_month.'-01';
|
||||
foreach($orgs as $org) {
|
||||
$count = $this->org_events_count($user, $org, $target_month, $target_year);
|
||||
if($options['logarithmic'] === "true" || $options['logarithmic'] === "1") {
|
||||
$item[$org['Organisation']['name']] = (int) round(log($count, 1.1)); // taking the logarithmic view
|
||||
} else if(empty($options['logarithmic']) || $options['logarithmic'] === "true" || $options['logarithmic'] === "1"){
|
||||
$item[$org['Organisation']['name']] = $count;
|
||||
}
|
||||
// if a positive score is detected at least once it's enough to be
|
||||
// considered for the graph
|
||||
if($count > 0) {
|
||||
unset($ghost_orgs[$org['Organisation']['name']]);
|
||||
}
|
||||
}
|
||||
$data['data'][] = $item;
|
||||
}
|
||||
$this->filter_ghost_orgs($data, $ghost_orgs);
|
||||
return $data;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
class OrganisationListWidget
|
||||
{
|
||||
public $title = 'Organisation list';
|
||||
public $render = 'BarChart';
|
||||
public $description = 'The countries represented via organisations on the current instance.';
|
||||
public $width = 3;
|
||||
public $height = 4;
|
||||
public $params = [
|
||||
'filter' => 'A list of filters by organisation meta information (sector, type, local (- expects a boolean or a list of boolean values)) to include. (dictionary, prepending values with ! uses them as a negation)',
|
||||
'limit' => 'Limits the number of displayed tags. Default: 10'
|
||||
];
|
||||
public $cacheLifetime = null;
|
||||
public $autoRefreshDelay = false;
|
||||
private $validFilterKeys = [
|
||||
'sector',
|
||||
'type',
|
||||
'local'
|
||||
];
|
||||
public $placeholder =
|
||||
'{
|
||||
"filter": {
|
||||
"type": "Member",
|
||||
"local": [0,1]
|
||||
}
|
||||
}';
|
||||
private $Organisation = null;
|
||||
|
||||
public $countryCodes = [];
|
||||
|
||||
public function handler($user, $options = array())
|
||||
{
|
||||
App::uses('WidgetToolkit', 'Lib/Dashboard/Tools');
|
||||
$WidgetToolkit = new WidgetToolkit();
|
||||
$this->countryCodes = $WidgetToolkit->getCountryCodeMapping();
|
||||
$params = [
|
||||
'conditions' => [
|
||||
'Nationality !=' => ''
|
||||
]
|
||||
];
|
||||
if (!empty($options['filter']) && is_array($options['filter'])) {
|
||||
foreach ($this->validFilterKeys as $filterKey) {
|
||||
if (!empty($options['filter'][$filterKey])) {
|
||||
if (!is_array($options['filter'][$filterKey])) {
|
||||
$options['filter'][$filterKey] = [$options['filter'][$filterKey]];
|
||||
}
|
||||
$tempConditionBucket = [];
|
||||
foreach ($options['filter'][$filterKey] as $value) {
|
||||
if ($value[0] === '!') {
|
||||
$tempConditionBucket['Organisation.' . $filterKey . ' NOT IN'][] = mb_substr($value, 1);
|
||||
} else {
|
||||
$tempConditionBucket['Organisation.' . $filterKey . ' IN'][] = $value;
|
||||
}
|
||||
}
|
||||
if (!empty($tempConditionBucket)) {
|
||||
$params['conditions']['AND'][] = $tempConditionBucket;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->Organisation = ClassRegistry::init('Organisation');
|
||||
$orgs = $this->Organisation->find('all', [
|
||||
'recursive' => -1,
|
||||
'fields' => ['Organisation.nationality', 'COUNT(Organisation.nationality) AS frequency'],
|
||||
'conditions' => $params['conditions'],
|
||||
'group' => ['Organisation.nationality']
|
||||
]);
|
||||
$results = [];
|
||||
foreach($orgs as $org) {
|
||||
$country = $org['Organisation']['nationality'];
|
||||
$count = $org['0']['frequency'];
|
||||
if (isset($this->countryCodes[$country])) {
|
||||
$countryCode = $this->countryCodes[$country];
|
||||
$results[$countryCode] = $count;
|
||||
}
|
||||
}
|
||||
arsort($results);
|
||||
return ['data' => $results];
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -26,188 +26,13 @@ class OrganisationMapWidget
|
|||
}';
|
||||
private $Organisation = null;
|
||||
|
||||
public $countryCodes = array(
|
||||
'Afghanistan' => 'AF',
|
||||
'Albania' => 'AL',
|
||||
'Algeria' => 'DZ',
|
||||
'Angola' => 'AO',
|
||||
'Argentina' => 'AR',
|
||||
'Armenia' => 'AM',
|
||||
'Australia' => 'AU',
|
||||
'Austria' => 'AT',
|
||||
'Azerbaijan' => 'AZ',
|
||||
'Bahamas' => 'BS',
|
||||
'Bangladesh' => 'BD',
|
||||
'Belarus' => 'BY',
|
||||
'Belgium' => 'BE',
|
||||
'Belize' => 'BZ',
|
||||
'Benin' => 'BJ',
|
||||
'Bhutan' => 'BT',
|
||||
'Bolivia' => 'BO',
|
||||
'Bosnia and Herz.' => 'BA',
|
||||
'Botswana' => 'BW',
|
||||
'Brazil' => 'BR',
|
||||
'Brunei' => 'BN',
|
||||
'Bulgaria' => 'BG',
|
||||
'Burkina Faso' => 'BF',
|
||||
'Burundi' => 'BI',
|
||||
'Cambodia' => 'KH',
|
||||
'Cameroon' => 'CM',
|
||||
'Canada' => 'CA',
|
||||
'Central African Rep.' => 'CF',
|
||||
'Chad' => 'TD',
|
||||
'Chile' => 'CL',
|
||||
'China' => 'CN',
|
||||
'Colombia' => 'CO',
|
||||
'Congo' => 'CG',
|
||||
'Costa Rica' => 'CR',
|
||||
'Croatia' => 'HR',
|
||||
'Cuba' => 'CU',
|
||||
'Cyprus' => 'CY',
|
||||
'Czech Rep.' => 'CZ',
|
||||
'Czech Republic' => 'CZ',
|
||||
'Côte d\'Ivoire' => 'CI',
|
||||
'Dem. Rep. Congo' => 'CD',
|
||||
'Dem. Rep. Korea' => 'KP',
|
||||
'Denmark' => 'DK',
|
||||
'Djibouti' => 'DJ',
|
||||
'Dominican Rep.' => 'DO',
|
||||
'Ecuador' => 'EC',
|
||||
'Egypt' => 'EG',
|
||||
'El Salvador' => 'SV',
|
||||
'Eq. Guinea' => 'GQ',
|
||||
'Eritrea' => 'ER',
|
||||
'Estonia' => 'EE',
|
||||
'Ethiopia' => 'ET',
|
||||
'Falkland Is.' => 'FK',
|
||||
'Fiji' => 'FJ',
|
||||
'Finland' => 'FI',
|
||||
'Fr. S. Antarctic Lands' => 'TF',
|
||||
'France' => 'FR',
|
||||
'Gabon' => 'GA',
|
||||
'Gambia' => 'GM',
|
||||
'Georgia' => 'GE',
|
||||
'Germany' => 'DE',
|
||||
'Ghana' => 'GH',
|
||||
'Greece' => 'GR',
|
||||
'Greenland' => 'GL',
|
||||
'Guatemala' => 'GT',
|
||||
'Guinea' => 'GN',
|
||||
'Guinea-Bissau' => 'GW',
|
||||
'Guyana' => 'GY',
|
||||
'Haiti' => 'HT',
|
||||
'Honduras' => 'HN',
|
||||
'Hungary' => 'HU',
|
||||
'Iceland' => 'IS',
|
||||
'India' => 'IN',
|
||||
'Indonesia' => 'ID',
|
||||
'Iran' => 'IR',
|
||||
'Iraq' => 'IQ',
|
||||
'Ireland' => 'IE',
|
||||
'Ireland {Republic}' => 'IE',
|
||||
'Israel' => 'IL',
|
||||
'Italy' => 'IT',
|
||||
'Jamaica' => 'JM',
|
||||
'Japan' => 'JP',
|
||||
'Jordan' => 'JO',
|
||||
'Kazakhstan' => 'KZ',
|
||||
'Kenya' => 'KE',
|
||||
'Korea' => 'KR',
|
||||
'Kuwait' => 'KW',
|
||||
'Kyrgyzstan' => 'KG',
|
||||
'Lao PDR' => 'LA',
|
||||
'Latvia' => 'LV',
|
||||
'Lebanon' => 'LB',
|
||||
'Lesotho' => 'LS',
|
||||
'Liberia' => 'LR',
|
||||
'Libya' => 'LY',
|
||||
'Lithuania' => 'LT',
|
||||
'Luxembourg' => 'LU',
|
||||
'Macedonia' => 'MK',
|
||||
'Madagascar' => 'MG',
|
||||
'Mainland China' => 'CN',
|
||||
'Malawi' => 'MW',
|
||||
'Malaysia' => 'MY',
|
||||
'Mali' => 'ML',
|
||||
'Malta' => 'MT',
|
||||
'Mauritania' => 'MR',
|
||||
'Mexico' => 'MX',
|
||||
'Moldova' => 'MD',
|
||||
'Mongolia' => 'MN',
|
||||
'Montenegro' => 'ME',
|
||||
'Morocco' => 'MA',
|
||||
'Mozamb' => 'MZ',
|
||||
'Myanmar' => 'MM',
|
||||
'Namibia' => 'NA',
|
||||
'Nepal' => 'NP',
|
||||
'Netherlands' => 'NL',
|
||||
'New Caledonia' => 'NC',
|
||||
'New Zealand' => 'NZ',
|
||||
'Nicaragua' => 'NI',
|
||||
'Niger' => 'NE',
|
||||
'Nigeria' => 'NG',
|
||||
'Norway' => 'NO',
|
||||
'Oman' => 'OM',
|
||||
'Pakistan' => 'PK',
|
||||
'Palestine' => 'PS',
|
||||
'Panama' => 'PA',
|
||||
'Papua New Guinea' => 'PG',
|
||||
'Paraguay' => 'PY',
|
||||
'Peru' => 'PE',
|
||||
'Philippines' => 'PH',
|
||||
'Poland' => 'PL',
|
||||
'Portugal' => 'PT',
|
||||
'Puerto Rico' => 'PR',
|
||||
'Qatar' => 'QA',
|
||||
'Romania' => 'RO',
|
||||
'Russia' => 'RU',
|
||||
'Rwanda' => 'RW',
|
||||
'S. Sudan' => 'SS',
|
||||
'Saudi Arabia' => 'SA',
|
||||
'Senegal' => 'SN',
|
||||
'Serbia' => 'RS',
|
||||
'Sierra Leone' => 'SL',
|
||||
'Slovakia' => 'SK',
|
||||
'Slovenia' => 'SI',
|
||||
'Solomon Is.' => 'SB',
|
||||
'Somalia' => 'SO',
|
||||
'South Africa' => 'ZA',
|
||||
'Spain' => 'ES',
|
||||
'Sri Lanka' => 'LK',
|
||||
'Sudan' => 'SD',
|
||||
'Suriname' => 'SR',
|
||||
'Swaziland' => 'SZ',
|
||||
'Sweden' => 'SE',
|
||||
'Switzerland' => 'CH',
|
||||
'Syria' => 'SY',
|
||||
'Taiwan' => 'TW',
|
||||
'Tajikistan' => 'TJ',
|
||||
'Tanzania' => 'TZ',
|
||||
'Thailand' => 'TH',
|
||||
'Timor-Leste' => 'TL',
|
||||
'Togo' => 'TG',
|
||||
'Trinidad and Tobago' => 'TT',
|
||||
'Tunisia' => 'TN',
|
||||
'Turkey' => 'TR',
|
||||
'Turkmenistan' => 'TM',
|
||||
'Uganda' => 'UG',
|
||||
'Ukraine' => 'UA',
|
||||
'United Arab Emirates' => 'AE',
|
||||
'United Kingdom' => 'GB',
|
||||
'United States' => 'US',
|
||||
'Uruguay' => 'UY',
|
||||
'Uzbekistan' => 'UZ',
|
||||
'Vanuatu' => 'VU',
|
||||
'Venezuela' => 'VE',
|
||||
'Vietnam' => 'VN',
|
||||
'W. Sahara' => 'EH',
|
||||
'Yemen' => 'YE',
|
||||
'Zambia' => 'ZM',
|
||||
'Zimbabwe' => 'ZW'
|
||||
);
|
||||
public $countryCodes = [];
|
||||
|
||||
public function handler($user, $options = array())
|
||||
{
|
||||
App::uses('WidgetToolkit', 'Lib/Dashboard/Tools');
|
||||
$WidgetToolkit = new WidgetToolkit();
|
||||
$this->countryCodes = $WidgetToolkit->getCountryCodeMapping();
|
||||
$params = [
|
||||
'conditions' => [
|
||||
'Nationality !=' => ''
|
||||
|
|
|
@ -0,0 +1,189 @@
|
|||
<?php
|
||||
|
||||
class WidgetToolkit
|
||||
{
|
||||
|
||||
public function getCountryCodeMapping(): array
|
||||
{
|
||||
return [
|
||||
'Afghanistan' => 'AF',
|
||||
'Albania' => 'AL',
|
||||
'Algeria' => 'DZ',
|
||||
'Angola' => 'AO',
|
||||
'Argentina' => 'AR',
|
||||
'Armenia' => 'AM',
|
||||
'Australia' => 'AU',
|
||||
'Austria' => 'AT',
|
||||
'Azerbaijan' => 'AZ',
|
||||
'Bahamas' => 'BS',
|
||||
'Bangladesh' => 'BD',
|
||||
'Belarus' => 'BY',
|
||||
'Belgium' => 'BE',
|
||||
'Belize' => 'BZ',
|
||||
'Benin' => 'BJ',
|
||||
'Bhutan' => 'BT',
|
||||
'Bolivia' => 'BO',
|
||||
'Bosnia and Herz.' => 'BA',
|
||||
'Botswana' => 'BW',
|
||||
'Brazil' => 'BR',
|
||||
'Brunei' => 'BN',
|
||||
'Bulgaria' => 'BG',
|
||||
'Burkina Faso' => 'BF',
|
||||
'Burundi' => 'BI',
|
||||
'Cambodia' => 'KH',
|
||||
'Cameroon' => 'CM',
|
||||
'Canada' => 'CA',
|
||||
'Central African Rep.' => 'CF',
|
||||
'Chad' => 'TD',
|
||||
'Chile' => 'CL',
|
||||
'China' => 'CN',
|
||||
'Colombia' => 'CO',
|
||||
'Congo' => 'CG',
|
||||
'Costa Rica' => 'CR',
|
||||
'Croatia' => 'HR',
|
||||
'Cuba' => 'CU',
|
||||
'Cyprus' => 'CY',
|
||||
'Czech Rep.' => 'CZ',
|
||||
'Czech Republic' => 'CZ',
|
||||
'Côte d\'Ivoire' => 'CI',
|
||||
'Dem. Rep. Congo' => 'CD',
|
||||
'Dem. Rep. Korea' => 'KP',
|
||||
'Denmark' => 'DK',
|
||||
'Djibouti' => 'DJ',
|
||||
'Dominican Rep.' => 'DO',
|
||||
'Ecuador' => 'EC',
|
||||
'Egypt' => 'EG',
|
||||
'El Salvador' => 'SV',
|
||||
'Eq. Guinea' => 'GQ',
|
||||
'Eritrea' => 'ER',
|
||||
'Estonia' => 'EE',
|
||||
'Ethiopia' => 'ET',
|
||||
'Falkland Is.' => 'FK',
|
||||
'Fiji' => 'FJ',
|
||||
'Finland' => 'FI',
|
||||
'Fr. S. Antarctic Lands' => 'TF',
|
||||
'France' => 'FR',
|
||||
'Gabon' => 'GA',
|
||||
'Gambia' => 'GM',
|
||||
'Georgia' => 'GE',
|
||||
'Germany' => 'DE',
|
||||
'Ghana' => 'GH',
|
||||
'Greece' => 'GR',
|
||||
'Greenland' => 'GL',
|
||||
'Guatemala' => 'GT',
|
||||
'Guinea' => 'GN',
|
||||
'Guinea-Bissau' => 'GW',
|
||||
'Guyana' => 'GY',
|
||||
'Haiti' => 'HT',
|
||||
'Honduras' => 'HN',
|
||||
'Hungary' => 'HU',
|
||||
'Iceland' => 'IS',
|
||||
'India' => 'IN',
|
||||
'Indonesia' => 'ID',
|
||||
'Iran' => 'IR',
|
||||
'Iraq' => 'IQ',
|
||||
'Ireland' => 'IE',
|
||||
'Ireland {Republic}' => 'IE',
|
||||
'Israel' => 'IL',
|
||||
'Italy' => 'IT',
|
||||
'Jamaica' => 'JM',
|
||||
'Japan' => 'JP',
|
||||
'Jordan' => 'JO',
|
||||
'Kazakhstan' => 'KZ',
|
||||
'Kenya' => 'KE',
|
||||
'Korea' => 'KR',
|
||||
'Kuwait' => 'KW',
|
||||
'Kyrgyzstan' => 'KG',
|
||||
'Lao PDR' => 'LA',
|
||||
'Latvia' => 'LV',
|
||||
'Lebanon' => 'LB',
|
||||
'Lesotho' => 'LS',
|
||||
'Liberia' => 'LR',
|
||||
'Libya' => 'LY',
|
||||
'Lithuania' => 'LT',
|
||||
'Luxembourg' => 'LU',
|
||||
'Macedonia' => 'MK',
|
||||
'Madagascar' => 'MG',
|
||||
'Mainland China' => 'CN',
|
||||
'Malawi' => 'MW',
|
||||
'Malaysia' => 'MY',
|
||||
'Mali' => 'ML',
|
||||
'Malta' => 'MT',
|
||||
'Mauritania' => 'MR',
|
||||
'Mexico' => 'MX',
|
||||
'Moldova' => 'MD',
|
||||
'Mongolia' => 'MN',
|
||||
'Montenegro' => 'ME',
|
||||
'Morocco' => 'MA',
|
||||
'Mozamb' => 'MZ',
|
||||
'Myanmar' => 'MM',
|
||||
'Namibia' => 'NA',
|
||||
'Nepal' => 'NP',
|
||||
'Netherlands' => 'NL',
|
||||
'New Caledonia' => 'NC',
|
||||
'New Zealand' => 'NZ',
|
||||
'Nicaragua' => 'NI',
|
||||
'Niger' => 'NE',
|
||||
'Nigeria' => 'NG',
|
||||
'Norway' => 'NO',
|
||||
'Oman' => 'OM',
|
||||
'Pakistan' => 'PK',
|
||||
'Palestine' => 'PS',
|
||||
'Panama' => 'PA',
|
||||
'Papua New Guinea' => 'PG',
|
||||
'Paraguay' => 'PY',
|
||||
'Peru' => 'PE',
|
||||
'Philippines' => 'PH',
|
||||
'Poland' => 'PL',
|
||||
'Portugal' => 'PT',
|
||||
'Puerto Rico' => 'PR',
|
||||
'Qatar' => 'QA',
|
||||
'Romania' => 'RO',
|
||||
'Russia' => 'RU',
|
||||
'Russian Federation' => 'RU',
|
||||
'Rwanda' => 'RW',
|
||||
'S. Sudan' => 'SS',
|
||||
'Saudi Arabia' => 'SA',
|
||||
'Senegal' => 'SN',
|
||||
'Serbia' => 'RS',
|
||||
'Sierra Leone' => 'SL',
|
||||
'Slovakia' => 'SK',
|
||||
'Slovenia' => 'SI',
|
||||
'Solomon Is.' => 'SB',
|
||||
'Somalia' => 'SO',
|
||||
'South Africa' => 'ZA',
|
||||
'Spain' => 'ES',
|
||||
'Sri Lanka' => 'LK',
|
||||
'Sudan' => 'SD',
|
||||
'Suriname' => 'SR',
|
||||
'Swaziland' => 'SZ',
|
||||
'Sweden' => 'SE',
|
||||
'Switzerland' => 'CH',
|
||||
'Syria' => 'SY',
|
||||
'Taiwan' => 'TW',
|
||||
'Tajikistan' => 'TJ',
|
||||
'Tanzania' => 'TZ',
|
||||
'Thailand' => 'TH',
|
||||
'Timor-Leste' => 'TL',
|
||||
'Togo' => 'TG',
|
||||
'Trinidad and Tobago' => 'TT',
|
||||
'Tunisia' => 'TN',
|
||||
'Turkey' => 'TR',
|
||||
'Turkmenistan' => 'TM',
|
||||
'Uganda' => 'UG',
|
||||
'Ukraine' => 'UA',
|
||||
'United Arab Emirates' => 'AE',
|
||||
'United Kingdom' => 'GB',
|
||||
'United States' => 'US',
|
||||
'Uruguay' => 'UY',
|
||||
'Uzbekistan' => 'UZ',
|
||||
'Vanuatu' => 'VU',
|
||||
'Venezuela' => 'VE',
|
||||
'Vietnam' => 'VN',
|
||||
'W. Sahara' => 'EH',
|
||||
'Yemen' => 'YE',
|
||||
'Zambia' => 'ZM',
|
||||
'Zimbabwe' => 'ZW'
|
||||
];
|
||||
}
|
||||
}
|
|
@ -38,7 +38,7 @@ class TrendingAttributesWidget
|
|||
$organisationModel = ClassRegistry::init('Organisation');
|
||||
if (!empty($options['org_filter']) && is_array($options['org_filter'])) {
|
||||
foreach ($this->validOrgFilters as $filterKey) {
|
||||
if (!empty($options['org_filter'][$filterKey])) {
|
||||
if (isset($options['org_filter'][$filterKey])) {
|
||||
if ($filterKey === 'local') {
|
||||
$tempConditionBucket['Organisation.local'] = $options['org_filter']['local'];
|
||||
} else {
|
||||
|
@ -72,9 +72,10 @@ class TrendingAttributesWidget
|
|||
/** @var Event $eventModel */
|
||||
$attributeModel = ClassRegistry::init('Attribute');
|
||||
$threshold = empty($options['threshold']) ? 10 : $options['threshold'];
|
||||
$time_window = empty($options['time_window']) ? (7 * 24 * 60 * 60) : (int)$options['time_window'];
|
||||
if (is_string($time_window) && substr($time_window, -1) === 'd') {
|
||||
$time_window = ((int)substr($time_window, 0, -1)) * 24 * 60 * 60;
|
||||
if (is_string($options['time_window']) && substr($options['time_window'], -1) === 'd') {
|
||||
$time_window = ((int)substr($options['time_window'], 0, -1)) * 24 * 60 * 60;
|
||||
} else {
|
||||
$time_window = empty($options['time_window']) ? (7 * 24 * 60 * 60) : (int)$options['time_window'];
|
||||
}
|
||||
$conditions = $time_window === -1 ? [] : ['Attribute.timestamp >=' => time() - $time_window];
|
||||
$conditions['Attribute.deleted'] = 0;
|
||||
|
|
|
@ -30,9 +30,10 @@ class TrendingTagsWidget
|
|||
/** @var Event $eventModel */
|
||||
$eventModel = ClassRegistry::init('Event');
|
||||
$threshold = empty($options['threshold']) ? 10 : $options['threshold'];
|
||||
$time_window = empty($options['time_window']) ? (7 * 24 * 60 * 60) : $options['time_window'];
|
||||
if (is_string($time_window) && substr($time_window, -1) === 'd') {
|
||||
$time_window = ((int)substr($time_window, 0, -1)) * 24 * 60 * 60;
|
||||
if (is_string($options['time_window']) && substr($options['time_window'], -1) === 'd') {
|
||||
$time_window = ((int)substr($options['time_window'], 0, -1)) * 24 * 60 * 60;
|
||||
} else {
|
||||
$time_window = empty($options['time_window']) ? (7 * 24 * 60 * 60) : (int)$options['time_window'];
|
||||
}
|
||||
$params = $time_window === -1 ? [] : ['timestamp' => time() - $time_window];
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ class UserContributionToplistWidget
|
|||
public $params = [
|
||||
'days' => 'How many days back should the list go - for example, setting 7 will only show contributions in the past 7 days. (integer)',
|
||||
'month' => 'Who contributed most this month? (boolean)',
|
||||
'previous_month' => 'Who contributed most the previous, finished month? (boolean)',
|
||||
'year' => 'Which contributed most this year? (boolean)',
|
||||
'filter' => 'A list of filters by organisation meta information (nationality, sector, type, name, uuid, local (- expects a boolean or a list of boolean values)) to include. (dictionary, prepending values with ! uses them as a negation)',
|
||||
'limit' => 'Limits the number of displayed tags. Default: 10'
|
||||
|
@ -41,12 +42,26 @@ class UserContributionToplistWidget
|
|||
$condition = strtotime(sprintf("-%s days", $options['days']));
|
||||
} else if (!empty($options['month'])) {
|
||||
$condition = strtotime('first day of this month 00:00:00', time());
|
||||
} else if (!empty($options['previous_month'])) {
|
||||
$condition = strtotime('first day of previous month 00:00:00', time());
|
||||
$end_condition = strtotime('last day of last month 23:59:59', time());
|
||||
} else if (!empty($options['year'])) {
|
||||
$condition = strtotime('first day of this year 00:00:00', time());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return $condition;
|
||||
$conditions = [];
|
||||
if (!empty($condition)) {
|
||||
$datetime = new DateTime();
|
||||
$datetime->setTimestamp($condition);
|
||||
$conditions['Event.timestamp >='] = $datetime->format('Y-m-d H:i:s');
|
||||
}
|
||||
if (!empty($end_condition)) {
|
||||
$datetime = new DateTime();
|
||||
$datetime->setTimestamp($end_condition);
|
||||
$conditions['Event.timestamp <='] = $datetime->format('Y-m-d H:i:s');
|
||||
}
|
||||
return $conditions;
|
||||
}
|
||||
|
||||
|
||||
|
@ -55,7 +70,7 @@ class UserContributionToplistWidget
|
|||
$params = ['conditions' => []];
|
||||
$timeConditions = $this->timeConditions($options);
|
||||
if ($timeConditions) {
|
||||
$params['conditions']['AND'][] = ['Event.timestamp >=' => $timeConditions];
|
||||
$params['conditions']['AND'][] = $timeConditions;
|
||||
}
|
||||
if (!empty($options['filter']) && is_array($options['filter'])) {
|
||||
foreach ($this->validFilterKeys as $filterKey) {
|
||||
|
|
|
@ -83,6 +83,12 @@ abstract class StixExport
|
|||
if ($this->__empty_file) {
|
||||
$this->__tmp_file->close();
|
||||
$this->__tmp_file->delete();
|
||||
if (empty($this->__filenames)) {
|
||||
$framing = $this->getFraming();
|
||||
$tmpFile = new TmpFileTool();
|
||||
$tmpFile->write($framing['header'] . $framing['footer']);
|
||||
return $tmpFile;
|
||||
}
|
||||
} else {
|
||||
if (!empty($this->__event_galaxies)) {
|
||||
$this->__write_event_galaxies();
|
||||
|
|
|
@ -224,7 +224,6 @@ class AttributeValidationTool
|
|||
switch ($type) {
|
||||
case 'md5':
|
||||
case 'imphash':
|
||||
case 'telfhash':
|
||||
case 'sha1':
|
||||
case 'sha224':
|
||||
case 'sha256':
|
||||
|
@ -255,6 +254,11 @@ class AttributeValidationTool
|
|||
return true;
|
||||
}
|
||||
return __('Checksum has an invalid length or format (expected: at least 35 hexadecimal characters, optionally starting with t1 instead of hexadecimal characters). Please double check the value or select type "other".');
|
||||
case 'telfhash':
|
||||
if (self::isTelfhashValid($value)) {
|
||||
return true;
|
||||
}
|
||||
return __('Checksum has an invalid length or format (expected: %s or %s hexadecimal characters). Please double check the value or select type "other".', 70, 72);
|
||||
case 'pehash':
|
||||
if (self::isHashValid('pehash', $value)) {
|
||||
return true;
|
||||
|
@ -635,6 +639,15 @@ class AttributeValidationTool
|
|||
return strlen($value) > 35 && ctype_xdigit($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
* @return bool
|
||||
*/
|
||||
private static function isTelfhashValid($value)
|
||||
{
|
||||
return strlen($value) == 70 || strlen($value) == 72;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
class SyncTool
|
||||
{
|
||||
|
||||
const ALLOWED_CERT_FILE_EXTENSIONS = ['pem', 'crt'];
|
||||
|
||||
/**
|
||||
* Take a server as parameter and return a HttpSocket object using the ssl options defined in the server settings
|
||||
* @param array|null $server
|
||||
|
@ -15,10 +18,10 @@ class SyncTool
|
|||
$params = ['compress' => true];
|
||||
if (!empty($server)) {
|
||||
if (!empty($server[$model]['cert_file'])) {
|
||||
$params['ssl_cafile'] = APP . "files" . DS . "certs" . DS . $server[$model]['id'] . '.pem';
|
||||
$params['ssl_cafile'] = APP . "files" . DS . "certs" . DS . $server[$model]['cert_file'];
|
||||
}
|
||||
if (!empty($server[$model]['client_cert_file'])) {
|
||||
$params['ssl_local_cert'] = APP . "files" . DS . "certs" . DS . $server[$model]['id'] . '_client.pem';
|
||||
$params['ssl_local_cert'] = APP . "files" . DS . "certs" . DS . $server[$model]['client_cert_file'];
|
||||
}
|
||||
if (!empty($server[$model]['self_signed'])) {
|
||||
$params['ssl_allow_self_signed'] = true;
|
||||
|
|
|
@ -85,7 +85,7 @@ class AppModel extends Model
|
|||
93 => false, 94 => false, 95 => true, 96 => false, 97 => true, 98 => false,
|
||||
99 => false, 100 => false, 101 => false, 102 => false, 103 => false, 104 => false,
|
||||
105 => false, 106 => false, 107 => false, 108 => false, 109 => false, 110 => false,
|
||||
111 => false, 112 => false, 113 => true
|
||||
111 => false, 112 => false, 113 => true, 114 => false
|
||||
);
|
||||
|
||||
const ADVANCED_UPDATES_DESCRIPTION = array(
|
||||
|
@ -1970,6 +1970,9 @@ class AppModel extends Model
|
|||
$this->cleanCacheFiles();
|
||||
$sqlArray[] = "UPDATE roles SET perm_view_feed_correlations = 1;";
|
||||
break;
|
||||
case 114:
|
||||
$indexArray[] = ['object_references', 'uuid'];
|
||||
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;';
|
||||
|
|
|
@ -219,9 +219,9 @@ class AuthKey extends AppModel
|
|||
$user['authkey_read_only'] = (bool)$authkey['AuthKey']['read_only'];
|
||||
|
||||
if ($authkey['AuthKey']['read_only']) {
|
||||
// Disable all permissions, keep just `perm_auth` unchanged
|
||||
// Disable all permissions, keep just `perm_auth` and `perm_audit` unchanged
|
||||
foreach ($user['Role'] as $key => &$value) {
|
||||
if (substr($key, 0, 5) === 'perm_' && $key !== 'perm_auth') {
|
||||
if (substr($key, 0, 5) === 'perm_' && $key !== 'perm_auth' && $key !== 'perm_audit') {
|
||||
$value = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2862,10 +2862,35 @@ class Event extends AppModel
|
|||
return $conditions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
private static function compressIpv6($value)
|
||||
{
|
||||
if (strpos($value, ':') && $converted = inet_pton($value)) {
|
||||
return inet_ntop($converted);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function set_filter_value(&$params, $conditions, $options)
|
||||
{
|
||||
if (!empty($params['value'])) {
|
||||
$params[$options['filter']] = $this->convert_filters($params['value']);
|
||||
foreach (['OR', 'AND', 'NOT'] as $operand) {
|
||||
if (!empty($params[$options['filter']][$operand])) {
|
||||
foreach ($params[$options['filter']][$operand] as $k => $v) {
|
||||
if ($operand === 'NOT') {
|
||||
$v = mb_substr($v, 1);
|
||||
}
|
||||
if (filter_var($v, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
|
||||
$v = $this->compressIpv6($v);
|
||||
}
|
||||
$params[$options['filter']][$operand][$k] = $operand === 'NOT' ? '!' . $v : $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
$conditions = $this->generic_add_filter($conditions, $params['value'], ['Attribute.value1', 'Attribute.value2']);
|
||||
}
|
||||
|
||||
|
@ -4478,7 +4503,7 @@ class Event extends AppModel
|
|||
/** @var Job $job */
|
||||
$job = ClassRegistry::init('Job');
|
||||
$message = empty($sightingUuids) ? __('Publishing sightings.') : __('Publishing %s sightings.', count($sightingUuids));
|
||||
$jobId = $job->createJob($user, Job::WORKER_PRIO, 'publish_event', "Event ID: $id", $message);
|
||||
$jobId = $job->createJob($user, Job::WORKER_DEFAULT, 'publish_event', "Event ID: $id", $message);
|
||||
|
||||
$args = ['publish_sightings', $id, $passAlong, $jobId, $user['id']];
|
||||
if (!empty($sightingUuids)) {
|
||||
|
|
|
@ -44,6 +44,7 @@ class Log extends AppModel
|
|||
'export',
|
||||
'fetchEvent',
|
||||
'file_upload',
|
||||
'forgot',
|
||||
'galaxy',
|
||||
'include_formula',
|
||||
'load_module',
|
||||
|
@ -51,6 +52,7 @@ class Log extends AppModel
|
|||
'login_fail',
|
||||
'logout',
|
||||
'merge',
|
||||
'password_reset',
|
||||
'pruneUpdateLogs',
|
||||
'publish',
|
||||
'publish_sightings',
|
||||
|
|
|
@ -6108,7 +6108,7 @@ class Server extends AppModel
|
|||
],
|
||||
'thumbnail_in_redis' => [
|
||||
'level' => self::SETTING_OPTIONAL,
|
||||
'description' => __('Store image thumbnails in Redis insteadof file system.'),
|
||||
'description' => __('Store image thumbnails in Redis instead of file system.'),
|
||||
'value' => false,
|
||||
'test' => 'testBool',
|
||||
'type' => 'boolean',
|
||||
|
@ -6406,6 +6406,14 @@ class Server extends AppModel
|
|||
'type' => 'boolean',
|
||||
'null' => true
|
||||
),
|
||||
'otp_issuer' => array(
|
||||
'level' => 2,
|
||||
'description' => __('If OTP is enabled, set the issuer string to an arbitrary value. Otherwise, MISP will default to "[MISP.org] MISP".'),
|
||||
'value' => false,
|
||||
'test' => 'testForEmpty',
|
||||
'type' => 'string',
|
||||
'null' => true
|
||||
),
|
||||
'email_otp_enabled' => array(
|
||||
'level' => 2,
|
||||
'description' => __('Enable two step authentication with a OTP sent by email. Requires e-mailing to be enabled. Warning: You cannot use it in combination with external authentication plugins.'),
|
||||
|
@ -6457,6 +6465,14 @@ class Server extends AppModel
|
|||
'type' => 'boolean',
|
||||
'null' => true
|
||||
),
|
||||
'allow_password_forgotten' => array(
|
||||
'level' => 1,
|
||||
'description' => __('Enabling this setting will allow users to request automated password reset tokens via mail and initiate a reset themselves. Users with no encryption keys will not be able to use this feature.'),
|
||||
'value' => false,
|
||||
'test' => 'testBool',
|
||||
'type' => 'boolean',
|
||||
'null' => true
|
||||
),
|
||||
'self_registration_message' => array(
|
||||
'level' => 1,
|
||||
'bigField' => true,
|
||||
|
@ -7243,6 +7259,13 @@ class Server extends AppModel
|
|||
'test' => 'testBool',
|
||||
'type' => 'boolean'
|
||||
),
|
||||
'Sightings_enable_realtime_publish' => array(
|
||||
'level' => 1,
|
||||
'description' => __('By default, sightings will not be immediately pushed to connected instances, as this can have a heavy impact on the performance of sighting attributes. Enable realtime publishing to trigger the publishing of sightings immediately as they are added.'),
|
||||
'value' => false,
|
||||
'test' => 'testBool',
|
||||
'type' => 'boolean'
|
||||
),
|
||||
'CustomAuth_enable' => array(
|
||||
'level' => 2,
|
||||
'description' => __('Enable this functionality if you would like to handle the authentication via an external tool and authenticate with MISP using a custom header.'),
|
||||
|
|
|
@ -4,6 +4,8 @@ App::uses('EncryptedValue', 'Tools');
|
|||
App::uses('Folder', 'Utility');
|
||||
App::uses('File', 'Utility');
|
||||
App::uses('RandomTool', 'Tools');
|
||||
App::uses('JSONConverterTool', 'Tools');
|
||||
App::uses('JsonTool', 'Tools');
|
||||
|
||||
class TaxiiServer extends AppModel
|
||||
{
|
||||
|
@ -102,7 +104,11 @@ class TaxiiServer extends AppModel
|
|||
$this->Job->id = $jobId;
|
||||
foreach ($result as $event) {
|
||||
$temporaryFile = $this->temporaryFile($temporaryFolderPath);
|
||||
$temporaryFile->write(json_encode($event));
|
||||
$temporaryFile->write(
|
||||
JsonTool::encode(
|
||||
JSONConverterTool::convert($event, false, true)
|
||||
)
|
||||
);
|
||||
$temporaryFile->close();
|
||||
if ($jobId && $i % 10 == 0) {
|
||||
$this->Job->saveField('progress', intval((100 * $i) / $eventCount));
|
||||
|
|
|
@ -1229,6 +1229,15 @@ class User extends AppModel
|
|||
|
||||
public function extralog($user, $action = null, $description = null, $fieldsResult = null, $modifiedUser = null)
|
||||
{
|
||||
if (!is_array($user) && $user === 'SYSTEM') {
|
||||
$user = [
|
||||
'id' => 0,
|
||||
'email' => 'SYSTEM',
|
||||
'Organisation' => [
|
||||
'name' => 'SYSTEM'
|
||||
]
|
||||
];
|
||||
}
|
||||
// new data
|
||||
$model = 'User';
|
||||
$modelId = $user['id'];
|
||||
|
@ -2007,4 +2016,89 @@ class User extends AppModel
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function forgotRouter($email, $ip)
|
||||
{
|
||||
if (Configure::read('MISP.background_jobs')) {
|
||||
/** @var Job $job */
|
||||
$job = ClassRegistry::init('Job');
|
||||
$dummyUser = [
|
||||
'email' => 'SYSTEM',
|
||||
'org_id' => 0,
|
||||
'role_id' => 0
|
||||
];
|
||||
$jobId = $job->createJob($dummyUser, Job::WORKER_EMAIL, 'forgot_password', $email, 'Sending...');
|
||||
|
||||
$args = [
|
||||
'jobForgot',
|
||||
$email,
|
||||
$ip,
|
||||
$jobId,
|
||||
];
|
||||
|
||||
$this->getBackgroundJobsTool()->enqueue(
|
||||
BackgroundJobsTool::EMAIL_QUEUE,
|
||||
BackgroundJobsTool::CMD_ADMIN,
|
||||
$args,
|
||||
true,
|
||||
$jobId
|
||||
);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return $this->forgot($email);
|
||||
}
|
||||
}
|
||||
|
||||
public function forgot($email, $ip, $jobId = null)
|
||||
{
|
||||
$user = $this->find('first', [
|
||||
'recursive' => -1,
|
||||
'conditions' => [
|
||||
'User.email' => $email,
|
||||
'User.disabled' => 0
|
||||
]
|
||||
]);
|
||||
if (empty($user)) {
|
||||
return false;
|
||||
}
|
||||
$redis = $this->setupRedis();
|
||||
$token = RandomTool::random_str(true, 40, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
|
||||
$redis->set('misp:forgot:' . $token, $user['User']['id'], ['nx', 'ex' => 600]);
|
||||
$baseurl = Configure::check('MISP.external_baseurl') ? Configure::read('MISP.external_baseurl') : Configure::read('MISP.baseurl');
|
||||
$body = __(
|
||||
"Dear MISP user,\n\nyou have requested a password reset on the MISP instance at %s. Click the link below to change your password.\n\n%s\n\nThe link above is only valid for 10 minutes, feel free to request a new one if it has expired.\n\nIf you haven't requested a password reset, reach out to your admin team and let them know that someone has attempted it in your stead.\n\nMake sure you keep the contents of this e-mail confidential, do NOT ever forward it as it contains a reset token that is equivalent of a password if acted upon. The IP used to trigger the request was: %s\n\nBest regards,\nYour MISP admin team",
|
||||
$baseurl,
|
||||
$baseurl . '/users/password_reset/' . $token,
|
||||
$ip
|
||||
);
|
||||
$bodyNoEnc = __(
|
||||
"Dear MISP user,\n\nyou have requested a password reset on the MISP instance at %s, however, no valid encryption key was found for your user and thus we cannot deliver your reset token. Please get in touch with your org admin / with an instance site admin to ask for a reset.\n\nThe IP used to trigger the request was: %s\n\nBest regards,\nYour MISP admin team",
|
||||
$baseurl,
|
||||
$ip
|
||||
);
|
||||
$this->sendEmail($user, $body, $bodyNoEnc, __('MISP password reset'));
|
||||
return true;
|
||||
}
|
||||
|
||||
public function fetchForgottenPasswordUser($token)
|
||||
{
|
||||
if (!ctype_alnum($token)) {
|
||||
return false;
|
||||
}
|
||||
$redis = $this->setupRedis();
|
||||
$userId = $redis->get('misp:forgot:' . $token);
|
||||
if (empty($userId)) {
|
||||
return false;
|
||||
}
|
||||
$user = $this->getAuthUser($userId, true);
|
||||
return $user;
|
||||
}
|
||||
|
||||
public function purgeForgetToken($token)
|
||||
{
|
||||
$redis = $this->setupRedis();
|
||||
$userId = $redis->del('misp:forgot:' . $token);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -250,7 +250,8 @@ echo $this->element('/genericElements/IndexTable/index_table', [
|
|||
return $this->Acl->canModifyEvent($object) && empty($object['Event']['publish_timestamp']);
|
||||
},
|
||||
]
|
||||
]
|
||||
],
|
||||
'persistUrlParams' => ['results']
|
||||
]
|
||||
]);
|
||||
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
<div style="position:relative;margin-top:20px;">
|
||||
<?php
|
||||
echo $this->element('view_galaxy_matrix', $data);
|
||||
?>
|
||||
</div>
|
||||
|
|
@ -10,14 +10,18 @@
|
|||
empty($widget['config']) ? '[]' : h(json_encode($widget['config'])),
|
||||
h($widget['widget']),
|
||||
sprintf(
|
||||
'<div class="grid-stack-item-content"><div class="widgetTitle"><span class="widgetTitleText">%s</span> %s %s</div><div class="widgetContent">%s</div></div>',
|
||||
'<div class="grid-stack-item-content"><div class="widgetTitle"><span class="widgetTitleText">%s</span> %s %s %s</div><div class="widgetContent">%s</div></div>',
|
||||
empty($widget['config']['alias']) ? h($widget['title']) : h($widget['config']['alias']),
|
||||
sprintf(
|
||||
'<span class="fas fa-edit edit-widget" title="%s"></span>',
|
||||
'<span class="fas fa-download export-widget useCursorPointer" title="%s"></span>',
|
||||
__('Export raw data')
|
||||
),
|
||||
sprintf(
|
||||
'<span class="fas fa-edit edit-widget useCursorPointer" title="%s"></span>',
|
||||
__('Configure widget')
|
||||
),
|
||||
sprintf(
|
||||
'<span class="fas fa-trash remove-widget" title="%s"></span>',
|
||||
'<span class="fas fa-trash remove-widget useCursorPointer" title="%s"></span>',
|
||||
__('Remove widget')
|
||||
),
|
||||
' '
|
||||
|
|
|
@ -40,6 +40,9 @@
|
|||
} else {
|
||||
$params['class'] = '';
|
||||
}
|
||||
if (!empty($fieldData['autofocus'])) {
|
||||
$params['autofocus'] = 1;
|
||||
}
|
||||
if (empty($fieldData['type']) || $fieldData['type'] !== 'checkbox' ) {
|
||||
$params['class'] .= ' form-control';
|
||||
}
|
||||
|
|
|
@ -465,7 +465,7 @@
|
|||
array(
|
||||
'text' => __('Audit Logs'),
|
||||
'url' => $baseurl . '/admin/audit_logs/index',
|
||||
'requirement' => Configure::read('MISP.log_new_audit') && $isAdmin,
|
||||
'requirement' => Configure::read('MISP.log_new_audit') && $this->Acl->canAccess('auditLogs', 'admin_index'),
|
||||
),
|
||||
array(
|
||||
'text' => __('Access Logs'),
|
||||
|
@ -475,7 +475,7 @@
|
|||
array(
|
||||
'text' => __('Search Logs'),
|
||||
'url' => $baseurl . '/admin/logs/search',
|
||||
'requirement' => $isAdmin
|
||||
'requirement' => $this->Acl->canAccess('logs', 'admin_search')
|
||||
)
|
||||
)
|
||||
),
|
||||
|
|
|
@ -229,8 +229,8 @@
|
|||
}
|
||||
?>
|
||||
</td>
|
||||
<td class="short">
|
||||
<input type="text" class="ObjectComment" style="padding:0;height:20px;margin-bottom:0;" placeholder="<?php echo h($importComment); ?>"<?php if (!empty($object['comment'])) echo ' value="' . h($object['comment']) . '"';?>>
|
||||
<td class="bitwider">
|
||||
<textarea class="ObjectComment inline-input" cols="30" rows="6" placeholder="<?php echo h($importComment); ?>" oninput="autoresize(this)"><?php if (!empty($object['comment'])) echo h($object['comment']);?></textarea>
|
||||
</td>
|
||||
<td style="width:60px;text-align:center;">
|
||||
<select class="ObjectDistribution" style="padding:0;height:20px;margin-bottom:0;">
|
||||
|
@ -302,8 +302,8 @@
|
|||
<td class="short" style="width:40px;text-align:center;">
|
||||
<input type="checkbox" class="AttributeDisableCorrelation"<?php if (!empty($attribute['disable_correlation'])) echo ' checked'; ?>>
|
||||
</td>
|
||||
<td class="short">
|
||||
<input type="text" class="AttributeComment" style="padding:0;height:20px;margin-bottom:0;"<?php if (!empty($attribute['comment'])) echo ' value="' . h($attribute['comment']) . '"';?>>
|
||||
<td class="bitwider">
|
||||
<textarea class="AttributeComment inline-input" rows="1" oninput="autoresize(this)"><?php if (!empty($attribute['comment'])) echo h($attribute['comment']);?></textarea>
|
||||
</td>
|
||||
<td class="short" style="width:40px;text-align:center;">
|
||||
<select class="AttributeDistribution" style="padding:0;height:20px;margin-bottom:0;">
|
||||
|
@ -412,8 +412,8 @@
|
|||
<td class="short" style="width:40px;text-align:center;">
|
||||
<input type="checkbox" class="AttributeDisableCorrelation"<?php if (isset($attribute['disable_correlation']) && $attribute['disable_correlation']) echo ' checked'; ?>>
|
||||
</td>
|
||||
<td class="short">
|
||||
<input type="text" class="AttributeComment" style="padding:0;height:20px;margin-bottom:0;" placeholder="<?php echo h($importComment); ?>"<?php if (!empty($attribute['comment'])) echo ' value="' . h($attribute['comment']) . '"';?>>
|
||||
<td class="bitwider">
|
||||
<textarea class="AttributeComment inline-input" rows="1" oninput="autoresize(this)" placeholder="<?php echo h($importComment); ?>"><?php if (!empty($attribute['comment'])) echo h($attribute['comment']);?></textarea>
|
||||
</td>
|
||||
<td class="short" style="width:40px;text-align:center;">
|
||||
<select class="AttributeDistribution" style="padding:0;height:20px;margin-bottom:0;">
|
||||
|
|
|
@ -13,6 +13,11 @@ class LightPaginatorHelper extends PaginatorHelper
|
|||
return '';
|
||||
}
|
||||
|
||||
public function last($last = 'last >>', $options = array())
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function hasNext($model = null)
|
||||
{
|
||||
$model = $this->defaultModel();
|
||||
|
|
|
@ -91,16 +91,19 @@ echo $this->element('/genericElements/IndexTable/index_table', [
|
|||
],
|
||||
[
|
||||
'name' => __('Nationality'),
|
||||
'sort' => 'Organisation.nationality',
|
||||
'data_path' => 'Organisation',
|
||||
'class' => 'short',
|
||||
'element' => 'country',
|
||||
],
|
||||
[
|
||||
'name' => __('Sector'),
|
||||
'sort' => 'Organisation.sector',
|
||||
'data_path' => 'Organisation.sector',
|
||||
],
|
||||
[
|
||||
'name' => __('Type'),
|
||||
'sort' => 'Organisation.type',
|
||||
'data_path' => 'Organisation.type',
|
||||
],
|
||||
[
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
echo $this->element('genericElements/Form/genericForm', [
|
||||
'data' => [
|
||||
'description' => __("If you already are enrolled on this instance, but forgot your password, you can request a new password below.") . '<br />' . __("An e-mail containing URL with an embedded token will be sent to you that you can use to reset the password within 10 minutes."),
|
||||
'model' => 'User',
|
||||
'title' => __('Forgotten password'),
|
||||
'fields' => [
|
||||
[
|
||||
'field' => 'email',
|
||||
'class' => 'span6'
|
||||
],
|
||||
],
|
||||
'submit' => [
|
||||
'action' => $this->request->params['action'],
|
||||
'ajaxSubmit' => 'submitGenericFormInPlace();'
|
||||
]
|
||||
]
|
||||
]);
|
|
@ -59,6 +59,15 @@
|
|||
__('No account yet? Register now!')
|
||||
);
|
||||
?>
|
||||
<div class="clear">
|
||||
<?php
|
||||
echo empty(Configure::read('Security.allow_password_forgotten')) ? '' : sprintf(
|
||||
'<a href="%s/users/forgot" title="%s">%s</a>',
|
||||
$baseurl,
|
||||
__('Initiate a password reset.'),
|
||||
__('I have forgotten my password')
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
<?= $this->Form->button(__('Login'), array('class' => 'btn btn-primary')); ?>
|
||||
<?php
|
||||
|
|
|
@ -19,6 +19,7 @@ echo $this->element('/genericElements/Form/genericForm', array(
|
|||
"label" => $label,
|
||||
"type" => "text",
|
||||
"placeholder" => __("Enter your OTP here"),
|
||||
"autofocus" => 1
|
||||
)
|
||||
),
|
||||
"submit" => array (
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
<div class="users form">
|
||||
<?php echo $this->Form->create('User');?>
|
||||
<fieldset>
|
||||
<legend><?php echo __('Reset password'); ?></legend>
|
||||
<?php
|
||||
$passwordPopover = '<span class="blue bold">' . __('Minimal length') . '</span>: ' . h($length) . '<br>';
|
||||
$passwordPopover .= '<span class="blue bold">' . __('Complexity') . '</span>: ' . h($complexity);
|
||||
echo $this->Form->input('password', array(
|
||||
'label' => __('New password') . ' <span id="PasswordPopover" data-content="' . h($passwordPopover) . '" class="fas fa-info-circle"></span>', 'autofocus'
|
||||
));
|
||||
echo $this->Form->input('confirm_password', [
|
||||
'type' => 'password',
|
||||
'label' => __('Confirm new password'),
|
||||
'div' => array('class' => 'input password required'),
|
||||
]);
|
||||
?>
|
||||
</fieldset>
|
||||
<div style="border-bottom: 1px solid #e5e5e5;width:100%;"> </div>
|
||||
<div class="clear" style="margin-top:10px;">
|
||||
</div>
|
||||
<?php
|
||||
echo $this->Form->button(__('Submit'), array('class' => 'btn btn-primary'));
|
||||
echo $this->Form->end();
|
||||
?>
|
||||
</div>
|
|
@ -193,7 +193,7 @@ $debugEnabled = !empty($selectedWorkflow['Workflow']['debug_enabled']);
|
|||
<a href="#"><i class="fa-fw <?= $this->FontAwesome->getClass('file-import') ?>"></i> <?= __('Import blueprint') ?></a>
|
||||
<ul class="dropdown-menu pull-right">
|
||||
<?php if (empty($workflowBlueprints)) : ?>
|
||||
<li><a href="#"><?= _('No workflow blueprints saved') ?></a></li>
|
||||
<li><a href="#"><?= __('No workflow blueprints saved') ?></a></li>
|
||||
<?php endif; ?>
|
||||
<?php foreach ($workflowBlueprints as $workflowBlueprint) : ?>
|
||||
<li>
|
||||
|
@ -211,7 +211,7 @@ $debugEnabled = !empty($selectedWorkflow['Workflow']['debug_enabled']);
|
|||
<a href="#"><i class="fa-fw <?= $this->FontAwesome->getClass('edit') ?>"></i> <?= __('Edit existing blueprint') ?></a>
|
||||
<ul class="dropdown-menu pull-right disabled">
|
||||
<?php if (empty($workflowBlueprints)) : ?>
|
||||
<li><a href="#"><?= _('No workflow blueprints saved') ?></a></li>
|
||||
<li><a href="#"><?= __('No workflow blueprints saved') ?></a></li>
|
||||
<?php endif; ?>
|
||||
<?php foreach ($workflowBlueprints as $workflowBlueprint) : ?>
|
||||
<li class="control-edit-bp-blocks">
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
"kamisama/cake-resque": "4.1.2",
|
||||
"pear/crypt_gpg": "1.6.7",
|
||||
"monolog/monolog": "1.24.0",
|
||||
"thecodingmachine/safe": "^1.0",
|
||||
"spomky-labs/otphp": "^10.0",
|
||||
"bacon/bacon-qr-code": "^2.0"
|
||||
},
|
||||
|
@ -39,14 +38,16 @@
|
|||
"aws/aws-sdk-php": "To upload samples to S3",
|
||||
"jakub-onderka/openid-connect-php": "For OIDC authentication",
|
||||
"supervisorphp/supervisor": "For managing background jobs",
|
||||
"lstrojny/fxmlrpc": "Required for supervisorphp/supervisor XML-RPC requests",
|
||||
"guzzlehttp/guzzle": "Required for supervisorphp/supervisor XML-RPC requests",
|
||||
"lstrojny/fxmlrpc": "Required for supervisorphp/supervisor XML-RPC requests",
|
||||
"php-http/message": "Required for supervisorphp/supervisor XML-RPC requests",
|
||||
"spomky-labs/otphp": "Required for strong authentication with TOTP",
|
||||
"bacon/bacon-qr-code": "Required for strong authentication with TOTP"
|
||||
"php-http/message-factory": "Required for supervisorphp/supervisor XML-RPC requests"
|
||||
},
|
||||
"config": {
|
||||
"vendor-dir": "Vendor",
|
||||
"optimize-autoloader": true
|
||||
"optimize-autoloader": true,
|
||||
"allow-plugins": {
|
||||
"composer/installers": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -168,7 +168,7 @@
|
|||
"uuid": "53a830e6-8d07-4dd8-98d5-18cc4e66fc8c",
|
||||
"org_uuid": "",
|
||||
"org_name": "",
|
||||
"description": "The ultimate goal of the project is to develop a NATO capability, available to all NATO nations, through which nations commit to sharing their information. This community is only open for official government entities, sponsored by their nation representative in the NATO Multinational MISP Steering Board.",
|
||||
"description": "The ultimate goal of the project is to develop a NATO capability, available to all NATO nations, through which nations commit to sharing their information. This community is only open for official government cyber defense related entities, sponsored by their nation representative in the NATO Multinational MISP Steering Board.",
|
||||
"url": "https://misp.ncirc.nato.int",
|
||||
"sector": "Governmental",
|
||||
"nationality": "International",
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 734d57edf5e76900cd0c8d5d48d6f5910e29b84e
|
||||
Subproject commit 7028860c0aa8c471324008d3dc651b7ea9e07c0a
|
|
@ -1 +1 @@
|
|||
Subproject commit 2ca2667d7668067f906e9601e0c97a79d4c7ccf1
|
||||
Subproject commit da801ab146fb622a6447c8d2922a95b6049bb70a
|
|
@ -1 +1 @@
|
|||
Subproject commit 911aafb91a38a68bbf6f5474c06e77a039469c93
|
||||
Subproject commit 1a94fcd666bbf7eb505d4fbbc47ef6170c375706
|
|
@ -2,7 +2,7 @@
|
|||
RewriteEngine On
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteRule ^(.*)$ index.php?/$1 [QSA,L]
|
||||
RewriteRule ^(.*)$ index.php?/$1 "[QSA,L,B= ]"
|
||||
|
||||
# Adds AUTH support to Rest Plugin:
|
||||
RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization},last]
|
||||
|
|
|
@ -5515,6 +5515,26 @@ function resetDashboardGrid(grid, save = true) {
|
|||
grid.removeWidget(el);
|
||||
saveDashboardState();
|
||||
});
|
||||
$('.export-widget').click(function() {
|
||||
var $element = $(this).parent().parent().parent();
|
||||
var container_id = $element.attr('id').substring(7);
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: baseurl + '/dashboards/renderWidget/' + container_id + '/exportjson:1',
|
||||
data: {
|
||||
config: $element.attr('config'),
|
||||
widget: $element.attr('widget')
|
||||
},
|
||||
success:function (data) {
|
||||
data = JSON.stringify(data, null, 2);
|
||||
var blob=new Blob([data], {type: 'application/json'});
|
||||
var link=window.document.createElement('a');
|
||||
link.href=window.URL.createObjectURL(blob);
|
||||
link.download=$element.attr('widget') + "_" + container_id + "_export.json";
|
||||
link.click();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function setHomePage() {
|
||||
|
|
|
@ -9549,5 +9549,5 @@
|
|||
"uuid": false
|
||||
}
|
||||
},
|
||||
"db_version": "113"
|
||||
"db_version": "114"
|
||||
}
|
|
@ -411,7 +411,7 @@ apacheConfig_RHEL7 () {
|
|||
#sudo sed -i "s/SetHandler/\#SetHandler/g" /etc/httpd/conf.d/misp.ssl.conf
|
||||
sudo rm /etc/httpd/conf.d/ssl.conf
|
||||
sudo chmod 644 /etc/httpd/conf.d/misp.ssl.conf
|
||||
sudo sed -i '/Listen 80/a Listen 443' /etc/httpd/conf/httpd.conf
|
||||
sudo sed -i '/Listen 443/!s/Listen 80/a Listen 443/' /etc/httpd/conf/httpd.conf
|
||||
|
||||
# If a valid SSL certificate is not already created for the server, create a self-signed certificate:
|
||||
echo "The Common Name used below will be: ${OPENSSL_CN}"
|
||||
|
|
|
@ -452,7 +452,7 @@ apacheConfig_RHEL8 () {
|
|||
#sudo sed -i "s/SetHandler/\#SetHandler/g" /etc/httpd/conf.d/misp.ssl.conf
|
||||
sudo rm /etc/httpd/conf.d/ssl.conf
|
||||
sudo chmod 644 /etc/httpd/conf.d/misp.ssl.conf
|
||||
sudo sed -i '/Listen 80/a Listen 443' /etc/httpd/conf/httpd.conf
|
||||
sudo sed -i '/Listen 443/!s/Listen 80/a Listen 443/' /etc/httpd/conf/httpd.conf
|
||||
|
||||
# If a valid SSL certificate is not already created for the server, create a self-signed certificate:
|
||||
echo "The Common Name used below will be: ${OPENSSL_CN}"
|
||||
|
|
Loading…
Reference in New Issue