Merge branch 'main' into develop
commit
93612950ed
|
@ -89,13 +89,18 @@ try {
|
|||
if (file_exists(CONFIG . 'app_local.php')) {
|
||||
Configure::load('app_local', 'default');
|
||||
//Configure::load('cerebrate', 'default', true);
|
||||
$settingsFile = new File(CONFIG . 'config.json');
|
||||
if ($settingsFile->exists()) {
|
||||
$settings = file_get_contents(CONFIG . 'config.json');
|
||||
$settings = json_decode($settings, true);
|
||||
foreach ($settings as $path => $setting) {
|
||||
Configure::write($path, $setting);
|
||||
}
|
||||
|
||||
$settingsFile = new File(CONFIG . 'config.json');
|
||||
if ($settingsFile->exists()) {
|
||||
$settings = file_get_contents(CONFIG . 'config.json');
|
||||
$settings = json_decode($settings, true);
|
||||
foreach ($settings as $path => $setting) {
|
||||
if ($path == 'debug') {
|
||||
Configure::write($path, (bool) $setting);
|
||||
continue;
|
||||
}
|
||||
Configure::write($path, $setting);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -101,12 +101,15 @@ class AppController extends Controller
|
|||
|
||||
public function beforeFilter(EventInterface $event)
|
||||
{
|
||||
$this->loadModel('Settings');
|
||||
$this->Settings->loadSettings();
|
||||
$this->loadModel('Users');
|
||||
$this->Users->checkForNewInstance();
|
||||
if ($this->ParamHandler->isRest()) {
|
||||
$this->authApiUser();
|
||||
$this->Security->setConfig('unlockedActions', [$this->request->getParam('action')]);
|
||||
}
|
||||
|
||||
$this->ACL->setPublicInterfaces();
|
||||
if (!empty($this->request->getAttribute('identity'))) {
|
||||
$user = $this->Users->get($this->request->getAttribute('identity')->getIdentifier(), [
|
||||
|
|
|
@ -112,6 +112,7 @@ class CRUDComponent extends Component
|
|||
if (!$this->Controller->ParamHandler->isRest()) {
|
||||
$this->setRequestedEntryAmount();
|
||||
} else if (empty($this->request->getQuery('limit'))) {
|
||||
$this->Controller->paginate['maxLimit'] = PHP_INT_MAX;
|
||||
$this->Controller->paginate['limit'] = PHP_INT_MAX; // Make sure to download the entire filtered table
|
||||
}
|
||||
$data = $this->Controller->paginate($query, $this->Controller->paginate ?? []);
|
||||
|
@ -924,9 +925,10 @@ class CRUDComponent extends Component
|
|||
$tableSettings = IndexSetting::getTableSetting($user, $this->Table);
|
||||
if (!empty($tableSettings['number_of_element'])) {
|
||||
if ($tableSettings['number_of_element'] === 'all') {
|
||||
$tableSettings['number_of_element'] = 10000; // Even with all selecect, make sure not to return too much data for the browser
|
||||
$tableSettings['number_of_element'] = 10000; // Even with all selected, make sure not to return too much data for the browser
|
||||
}
|
||||
$this->Controller->paginate['limit'] = intval($tableSettings['number_of_element']);
|
||||
$this->Controller->paginate['maxLimit'] = $this->Controller->paginate['limit'];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,8 +14,8 @@ use Cake\Error\Debugger;
|
|||
|
||||
class EncryptionKeysController extends AppController
|
||||
{
|
||||
public $filterFields = ['owner_model', 'owner_id', 'encryption_key'];
|
||||
public $quickFilterFields = [['encryption_key' => true]];
|
||||
public $filterFields = ['owner_model', 'owner_id', 'encryption_key', 'Individuals.email', 'Organisations.name'];
|
||||
public $quickFilterFields = [['encryption_key' => true], ['Individuals.email' => true], ['Organisations.name' => true]];
|
||||
public $containFields = ['Individuals', 'Organisations'];
|
||||
public $statisticsFields = ['type'];
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ class OrganisationsController extends AppController
|
|||
$additionalContainFields[] = 'MetaFields';
|
||||
}
|
||||
$containFields = array_merge($this->containFields, $additionalContainFields);
|
||||
|
||||
$this->set('validOrgs', $this->Users->getValidOrgsForUser($this->ACL->getUser()));
|
||||
$this->CRUD->index([
|
||||
'filters' => $this->filterFields,
|
||||
'quickFilters' => $this->quickFilterFields,
|
||||
|
@ -184,9 +184,14 @@ class OrganisationsController extends AppController
|
|||
if ($currentUser['role']['perm_admin']) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($currentUser['role']['perm_org_admin'] && $currentUser['organisation']['id'] == $orgId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($currentUser['role']['perm_group_admin'] && in_array($orgId, $this->Users->getValidOrgsForUser($currentUser))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,7 +117,14 @@ class UsersController extends AppController
|
|||
$data['role_id'] = $defaultRole['id'];
|
||||
}
|
||||
if (!$currentUser['role']['perm_admin']) {
|
||||
$data['organisation_id'] = $currentUser['organisation_id'];
|
||||
$validOrgs = $this->Users->getValidOrgsForUser($currentUser);
|
||||
if ($currentUser['role']['perm_group_admin']) {
|
||||
if (!empty($data['organisation_id']) && !in_array($currentUser['organisation_id'], $validOrgs)) {
|
||||
throw new MethodNotAllowedException(__('You do not have permission to assign that organisation.'));
|
||||
}
|
||||
} else {
|
||||
$data['organisation_id'] = $currentUser['organisation_id'];
|
||||
}
|
||||
if (!in_array($data['role_id'], array_keys($validRoles))) {
|
||||
throw new MethodNotAllowedException(__('You do not have permission to assign that role.'));
|
||||
}
|
||||
|
@ -171,7 +178,8 @@ class UsersController extends AppController
|
|||
*/
|
||||
$org_conditions = [];
|
||||
if (empty($currentUser['role']['perm_admin'])) {
|
||||
$org_conditions = ['id' => $currentUser['organisation_id']];
|
||||
$validOrgs = $this->Users->getValidOrgsForUser($currentUser);
|
||||
$org_conditions = ['id IN' => $validOrgs];
|
||||
}
|
||||
$dropdownData = [
|
||||
'role' => $validRoles,
|
||||
|
|
|
@ -907,6 +907,12 @@ class MispConnector extends CommonConnectorTools
|
|||
'reload_url' => '/localTools/action/' . h($params['connection']['id']) . '/organisationsAction',
|
||||
'popover_url' => '/localTools/action/' . h($params['connection']['id']) . '/fetchSelectedOrganisationsAction'
|
||||
],
|
||||
[
|
||||
'text' => __('Fetch all organisations'),
|
||||
'html' => '<i class="fas fa-download"></i> ',
|
||||
'reload_url' => '/localTools/action/' . h($params['connection']['id']) . '/organisationsAction',
|
||||
'popover_url' => '/localTools/action/' . h($params['connection']['id']) . '/fetchSelectedOrganisationsAction?ids=all'
|
||||
],
|
||||
[
|
||||
'text' => __('Push organisations'),
|
||||
'html' => '<i class="fas fa-upload"></i> ',
|
||||
|
@ -1026,6 +1032,7 @@ class MispConnector extends CommonConnectorTools
|
|||
$data = $response->getJson();
|
||||
$temp = $this->getSharingGroups();
|
||||
$existingOrgs = [];
|
||||
$existingSGs = [];
|
||||
foreach ($temp as $k => $v) {
|
||||
$existingSGs[$v['uuid']] = $v;
|
||||
unset($temp[$k]);
|
||||
|
@ -1190,23 +1197,42 @@ class MispConnector extends CommonConnectorTools
|
|||
return [
|
||||
'data' => [
|
||||
'title' => __('Fetch organisations'),
|
||||
'description' => __('Fetch and create/update the selected {0} organisations from MISP?', count($ids)),
|
||||
'description' => is_array($ids) ?
|
||||
__('Fetch and create/update the selected {0} organisations from MISP?', count($ids)) :
|
||||
__('Fetch and create/update ALL organisations from MISP?'),
|
||||
'submit' => [
|
||||
'action' => $params['request']->getParam('action')
|
||||
],
|
||||
'url' => ['controller' => 'localTools', 'action' => 'action', $params['connection']['id'], 'fetchSelectedOrganisationsAction']
|
||||
'url' => is_array($ids) ?
|
||||
['controller' => 'localTools', 'action' => 'action', $params['connection']['id'], 'fetchSelectedOrganisationsAction'] :
|
||||
['controller' => 'localTools', 'action' => 'action', $params['connection']['id'], 'fetchSelectedOrganisationsAction?ids=all']
|
||||
]
|
||||
];
|
||||
} elseif ($params['request']->is(['post'])) {
|
||||
$successes = 0;
|
||||
$errors = 0;
|
||||
foreach ($ids as $id) {
|
||||
$response = $this->getData('/organisations/view/' . $id, $params);
|
||||
$result = $this->captureOrganisation($response->getJson()['Organisation']);
|
||||
if (!is_array($ids) && $ids === 'all') {
|
||||
$response = $this->getData('/organisations/index/scope:all', $params);
|
||||
if ($response->getStatusCode() == 200) {
|
||||
$successes++;
|
||||
} else {
|
||||
$errors++;
|
||||
$orgs = $response->getJson();
|
||||
foreach ($orgs as $org) {
|
||||
$result = $this->captureOrganisation($org['Organisation']);
|
||||
if ($result) {
|
||||
$successes++;
|
||||
} else {
|
||||
$errors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach ($ids as $id) {
|
||||
$response = $this->getData('/organisations/view/' . $id, $params);
|
||||
$result = $this->captureOrganisation($response->getJson()['Organisation']);
|
||||
if ($response->getStatusCode() == 200) {
|
||||
$successes++;
|
||||
} else {
|
||||
$errors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($successes) {
|
||||
|
|
|
@ -199,6 +199,9 @@ class AuthKeycloakBehavior extends Behavior
|
|||
'model_title' => __('Successful Keycloak enrollment for user {0}', $user['username']),
|
||||
'changed' => $logChange
|
||||
]);
|
||||
$saved_user = $this->getCerebrateUsers($user['id']);
|
||||
$clientId = $this->getClientId();
|
||||
$this->syncUsers($saved_user, $clientId);
|
||||
$response = $this->restApiRequest(
|
||||
'%s/admin/realms/%s/users/' . urlencode($newUserId) . '/execute-actions-email',
|
||||
['UPDATE_PASSWORD'],
|
||||
|
@ -335,7 +338,7 @@ class AuthKeycloakBehavior extends Behavior
|
|||
|
||||
public function getParsedKeycloakUser(): array
|
||||
{
|
||||
$response = $this->restApiRequest('%s/admin/realms/%s/users', [], 'get');
|
||||
$response = $this->restApiRequest('%s/admin/realms/%s/users/?max=999999', [], 'get');
|
||||
$keycloakUsers = json_decode($response->getStringBody(), true);
|
||||
$keycloakUsersParsed = [];
|
||||
$mappers = array_merge(['role_name', 'role_uuid', 'org_uuid', 'org_name'], $this->getMappedFieldList());
|
||||
|
@ -357,10 +360,10 @@ class AuthKeycloakBehavior extends Behavior
|
|||
return $keycloakUsersParsed;
|
||||
}
|
||||
|
||||
private function getCerebrateUsers(): array
|
||||
private function getCerebrateUsers($id = null): array
|
||||
{
|
||||
$metaFieldsSelector = ['fields' => ['MetaFields.field', 'MetaFields.parent_id', 'MetaFields.value']];
|
||||
$results = $this->_table->find()->contain(['Individuals', 'Organisations', 'Roles', 'MetaFields' => $metaFieldsSelector])->select([
|
||||
$query = $this->_table->find()->contain(['Individuals', 'Organisations', 'Roles', 'MetaFields' => $metaFieldsSelector])->select([
|
||||
'id',
|
||||
'uuid',
|
||||
'username',
|
||||
|
@ -373,7 +376,11 @@ class AuthKeycloakBehavior extends Behavior
|
|||
'Roles.uuid',
|
||||
'Organisations.name',
|
||||
'Organisations.uuid'
|
||||
])->disableHydration()->toArray();
|
||||
]);
|
||||
if ($id) {
|
||||
$query->where(['User.id' => $id]);
|
||||
}
|
||||
$results = $query->disableHydration()->toArray();
|
||||
foreach ($results as &$result) {
|
||||
if (!empty($result['meta_fields'])) {
|
||||
$temp = [];
|
||||
|
|
|
@ -29,7 +29,7 @@ class AuthKeysTable extends AppTable
|
|||
public function beforeMarshal(EventInterface $event, ArrayObject $data, ArrayObject $options)
|
||||
{
|
||||
$data['created'] = time();
|
||||
if (empty($data['expiration'])) {
|
||||
if (!isset($data['expiration'])) {
|
||||
$data['expiration'] = 0;
|
||||
} else {
|
||||
$data['expiration'] = strtotime($data['expiration']);
|
||||
|
@ -56,7 +56,16 @@ class AuthKeysTable extends AppTable
|
|||
{
|
||||
$validator
|
||||
->notEmptyString('user_id')
|
||||
->requirePresence(['user_id'], 'create');
|
||||
->requirePresence(['user_id'], 'create')
|
||||
->add('expiration', 'custom', [
|
||||
'rule' => function ($value, $context) {
|
||||
if ($value && $value < time()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
'message' => __('Expiration date/time has to be in the future.')
|
||||
]);
|
||||
return $validator;
|
||||
}
|
||||
|
||||
|
|
|
@ -62,6 +62,36 @@ class CerebrateSettingsProvider extends BaseSettingsProvider
|
|||
'test' => 'testUuid',
|
||||
],
|
||||
],
|
||||
'Session handling' => [
|
||||
'Session.defaults' => [
|
||||
'description' => 'The session handler used. We strongly recommend "php" and configuring the redis handler in your php.ini. Be advised, that database sessions require the creation of a session table first.',
|
||||
'default' => 'php',
|
||||
'name' => 'Session handler',
|
||||
'options' => function ($settingsProviders) {
|
||||
return [
|
||||
'php' => 'php',
|
||||
'cake' => 'cake',
|
||||
'database' => 'database'
|
||||
];
|
||||
},
|
||||
'severity' => 'info',
|
||||
'type' => 'select'
|
||||
],
|
||||
'Session.timeout' => [
|
||||
'description' => 'The session timeout (in minutes)',
|
||||
'default' => 30,
|
||||
'name' => 'Session Timeout',
|
||||
'severity' => 'info',
|
||||
'type' => 'integer',
|
||||
],
|
||||
'Session.ini.session.cookie_lifetime' => [
|
||||
'description' => 'The cookie timeout (in seconds). Whilst the session itself gets refreshed on each interaction, the cookie\'s timeout cannot be prolonged, so make sure that you set something at least as high as the session timeout, preferrably longer.',
|
||||
'default' => 604800,
|
||||
'name' => 'Cookie Timeout',
|
||||
'severity' => 'info',
|
||||
'type' => 'integer',
|
||||
],
|
||||
],
|
||||
/*
|
||||
'Miscellaneous' => [
|
||||
'sc2.hero' => [
|
||||
|
@ -316,9 +346,8 @@ class CerebrateSettingsProvider extends BaseSettingsProvider
|
|||
'description' => __('The debug level of the instance'),
|
||||
'default' => 0,
|
||||
'options' => [
|
||||
0 => __('Debug Off'),
|
||||
1 => __('Debug On'),
|
||||
2 => __('Debug On + SQL Dump'),
|
||||
false => __('Debug Off'),
|
||||
true => __('Debug On'),
|
||||
],
|
||||
'test' => function ($value, $setting, $validator) {
|
||||
$validator->range('value', [0, 2]);
|
||||
|
|
|
@ -126,7 +126,7 @@ class SettingsTable extends AppTable
|
|||
return $settings;
|
||||
}
|
||||
|
||||
private function loadSettings(): void
|
||||
public function loadSettings(): void
|
||||
{
|
||||
$settings = file_get_contents(CONFIG . 'config.json');
|
||||
$settings = json_decode($settings, true);
|
||||
|
|
|
@ -293,8 +293,18 @@ class UsersTable extends AppTable
|
|||
return true;
|
||||
}
|
||||
|
||||
public function getAllOrganisations($currentUser) {
|
||||
public function getAllOrganisations(\App\Model\Entity\User $currentUser)
|
||||
{
|
||||
$this->Individuals = TableRegistry::get('Individuals');
|
||||
return $this->Individuals->getAllOrganisations($currentUser);
|
||||
}
|
||||
|
||||
public function getValidOrgsForUser(\App\Model\Entity\User $user): array
|
||||
{
|
||||
if (!empty($user['role']['perm_group_admin'])) {
|
||||
return $this->Organisations->OrgGroups->getGroupOrgIdsForUser($user);
|
||||
} else {
|
||||
return [$user['organisation_id']];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ echo $this->element('genericElements/IndexTable/index_table', [
|
|||
'data_path' => 'origin',
|
||||
],
|
||||
[
|
||||
'name' => 'user',
|
||||
'name' => __('to'),
|
||||
'sort' => 'Inbox.user_id',
|
||||
'data_path' => 'user',
|
||||
'element' => 'user'
|
||||
|
|
|
@ -109,10 +109,13 @@ echo $this->element('genericElements/IndexTable/index_table', [
|
|||
'modal_params_data_path' => 'id',
|
||||
'icon' => 'edit',
|
||||
'complex_requirement' => [
|
||||
'function' => function ($row, $options) use ($loggedUser) {
|
||||
'function' => function ($row, $options) use ($loggedUser, $validOrgs) {
|
||||
if ($loggedUser['role']['perm_admin'] || ($loggedUser['role']['perm_org_admin'] && $row['id'] == $loggedUser['organisation']['id'])) {
|
||||
return true;
|
||||
}
|
||||
if ($loggedUser['role']['perm_group_admin'] && in_array($row['id'], $validOrgs)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
]
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
'type' => 'number',
|
||||
'min' => '0',
|
||||
'step' => 1,
|
||||
'value' => isset($setting['value']) ? h($setting['value']) : '',
|
||||
'id' => h($settingId),
|
||||
'data-setting-name' => h($settingName),
|
||||
'aria-describedby' => h("{$settingId}Help")
|
||||
|
|
Loading…
Reference in New Issue