new: [auth] Added authentication

remotes/origin/main
iglocska 2020-06-21 21:27:11 +02:00
parent d0f3314314
commit bdb005e341
No known key found for this signature in database
GPG Key ID: BEA224F1FEF113AC
8 changed files with 216 additions and 658 deletions

View File

@ -23,6 +23,11 @@ use Cake\Http\BaseApplication;
use Cake\Http\MiddlewareQueue;
use Cake\Routing\Middleware\AssetMiddleware;
use Cake\Routing\Middleware\RoutingMiddleware;
use Authentication\AuthenticationService;
use Authentication\AuthenticationServiceInterface;
use Authentication\AuthenticationServiceProviderInterface;
use Authentication\Middleware\AuthenticationMiddleware;
use Psr\Http\Message\ServerRequestInterface;
/**
* Application setup class.
@ -30,7 +35,7 @@ use Cake\Routing\Middleware\RoutingMiddleware;
* This defines the bootstrapping logic and middleware layers you
* want to use in your application.
*/
class Application extends BaseApplication
class Application extends BaseApplication implements AuthenticationServiceProviderInterface
{
/**
* Load all the application configuration and bootstrap logic.
@ -53,7 +58,7 @@ class Application extends BaseApplication
if (Configure::read('debug')) {
$this->addPlugin('DebugKit');
}
$this->addPlugin('Authentication');
// Load more plugins here
}
@ -81,8 +86,8 @@ class Application extends BaseApplication
// creating the middleware instance specify the cache config name by
// using it's second constructor argument:
// `new RoutingMiddleware($this, '_cake_routes_')`
->add(new RoutingMiddleware($this));
->add(new RoutingMiddleware($this))
->add(new AuthenticationMiddleware($this));
return $middlewareQueue;
}
@ -105,4 +110,37 @@ class Application extends BaseApplication
// Load more plugins here
}
/**
* Returns a service provider instance.
*
* @param \Psr\Http\Message\ServerRequestInterface $request Request
* @return \Authentication\AuthenticationServiceInterface
*/
public function getAuthenticationService(ServerRequestInterface $request): AuthenticationServiceInterface
{
$service = new AuthenticationService();
// Define where users should be redirected to when they are not authenticated
$service->setConfig([
'unauthenticatedRedirect' => '/users/login',
'queryParam' => 'redirect',
]);
$fields = [
'username' => 'username',
'password' => 'password'
];
// Load the authenticators. Session should be first.
$service->loadAuthenticator('Authentication.Session');
$service->loadAuthenticator('Authentication.Form', [
'fields' => $fields,
'loginUrl' => '/users/login'
]);
// Load identifiers
$service->loadIdentifier('Authentication.Password', compact('fields'));
return $service;
}
}

View File

@ -39,6 +39,7 @@ class AppController extends Controller
public $isRest = null;
public $restResponsePayload = null;
public $user = null;
/**
* Initialization hook method.
@ -56,7 +57,7 @@ class AppController extends Controller
$this->loadComponent('RequestHandler');
$this->loadComponent('Flash');
$this->loadComponent('RestResponse');
$this->loadComponent('ACL');
$this->loadComponent('Security');
$this->loadComponent('ParamHandler', [
'request' => $this->request
]);
@ -64,7 +65,11 @@ class AppController extends Controller
'request' => $this->request,
'table' => $this->{$this->modelClass}
]);
$this->loadComponent('Authentication.Authentication');
$this->loadComponent('ACL', [
'request' => $this->request,
'Authentication' => $this->Authentication
]);
if (Configure::read('debug')) {
Configure::write('DebugKit.panels', ['DebugKit.Packages' => true]);
Configure::write('DebugKit.forceEnable', true);
@ -80,6 +85,21 @@ class AppController extends Controller
public function beforeFilter(EventInterface $event)
{
$this->isAdmin = true;
$this->ACL->setPublicInterfaces();
if (!empty($this->request->getAttribute('identity'))) {
$this->loadModel('Users');
$user = $this->Users->get($this->request->getAttribute('identity')->getIdentifier(), [
'contain' => ['Roles', 'Individuals' => 'Organisations']
]);
if (!empty($user['disabled'])) {
$this->Authentication->logout();
$this->Flash->error(__('The user account is disabled.'));
return $this->redirect(['controller' => 'Users', 'action' => 'login']);
}
unset($user['password']);
$this->ACL->setUser($user);
}
$this->ACL->checkAccess();
$this->set('menu', $this->{$this->modelClass}->getMenu());
$this->set('ajax', $this->request->is('ajax'));
}
@ -94,4 +114,9 @@ class AppController extends Controller
{
return true;
}
public function queryACL()
{
$this->ACL->findMissingFunctionNames();
}
}

View File

@ -3,627 +3,44 @@
namespace App\Controller\Component;
use Cake\Controller\Component;
use App\Model\Entity\User;
use Cake\Http\Exception\NotFoundException;
use Cake\Http\Exception\MethodNotAllowedException;
use Cake\Http\Exception\ForbiddenException;
use Cake\ORM\TableRegistry;
class ACLComponent extends Component
{
private $user = null;
public function initialize(array $config): void
{
$this->request = $config['request'];
$this->Authentication = $config['Authentication'];
}
// syntax:
// $__aclList[$controller][$action] = $permission_rules
// $controller == '*' - any controller can have this action
// $action == array() - site admin only has access
// $action == [] - site admin only has access
// $action == '*' - any role has access
// $action == array('OR' => array()) - any role in the array has access
// $action == array('AND' => array()) - roles with all permissions in the array have access
// $action == array('OR' => []) - any role in the array has access
// $action == array('AND' => []) - roles with all permissions in the array have access
// If we add any new functionality to MISP and we don't add it to this list, it will only be visible to site admins.
private $__aclList = array(
'*' => array(
'blackhole' => array(),
'checkAction' => array(),
'checkAuthUser' => array(),
'checkExternalAuthUser' => array(),
'cleanModelCaches' => array(),
'debugACL' => array(),
'generateCount' => array(),
'getActions' => array(),
'pruneDuplicateUUIDs' => array(),
'queryACL' => array(),
'removeDuplicateEvents' => array(),
'restSearch' => array('*'),
'updateDatabase' => array(),
'upgrade2324' => array(),
),
'attributes' => array(
'add' => array('perm_add'),
'add_attachment' => array('perm_add'),
'add_threatconnect' => array('perm_add'),
'addTag' => array('perm_tagger'),
'attributeReplace' => array('perm_add'),
'attributeStatistics' => array('*'),
'bro' => array('*'),
'checkAttachments' => array(),
'checkComposites' => array('perm_admin'),
'checkOrphanedAttributes' => array(),
'delete' => array('perm_add'),
'deleteSelected' => array('perm_add'),
'describeTypes' => array('*'),
'download' => array('*'),
'downloadAttachment' => array('*'),
'downloadSample' => array('*'),
'edit' => array('perm_add'),
'editField' => array('perm_add'),
'editSelected' => array('perm_add'),
'exportSearch' => array('*'),
'fetchEditForm' => array('perm_add'),
'fetchViewValue' => array('*'),
'generateCorrelation' => array(),
'hoverEnrichment' => array('perm_add'),
'index' => array('*'),
'pruneOrphanedAttributes' => array(),
'removeTag' => array('perm_tagger'),
'reportValidationIssuesAttributes' => array(),
'restore' => array('perm_add'),
'restSearch' => array('*'),
'returnAttributes' => array('*'),
'rpz' => array('*'),
'search' => array('*'),
'searchAlternate' => array('*'),
'toggleCorrelation' => array('perm_add'),
'text' => array('*'),
'toggleToIDS' => array('perm_add'),
'updateAttributeValues' => array('perm_add'),
'view' => array('*'),
'viewPicture' => array('*'),
),
'dashboards' => array(
'getForm' => array('*'),
'index' => array('*'),
'updateSettings' => array('*'),
'getEmptyWidget' => array('*'),
'renderWidget' => array('*'),
'listTemplates' => array('*'),
'saveTemplate' => array('*'),
'export' => array('*'),
'import' => array('*'),
'deleteTemplate' => array('*')
),
'decayingModel' => array(
"update" => array(),
"export" => array('*'),
"import" => array('*'),
"view" => array('*'),
"index" => array('*'),
"add" => array( 'OR' => array('perm_admin', 'perm_decaying')),
"edit" => array( 'OR' => array('perm_admin', 'perm_decaying')),
"delete" => array( 'OR' => array('perm_admin', 'perm_decaying')),
"enable" => array( 'OR' => array('perm_admin', 'perm_decaying')),
"disable" => array( 'OR' => array('perm_admin', 'perm_decaying')),
"decayingTool" => array( 'OR' => array('perm_admin', 'perm_decaying')),
"getAllDecayingModels" => array('*'),
"decayingToolBasescore" => array('*'),
"decayingToolSimulation" => array('*'),
"decayingToolRestSearch" => array('*'),
"decayingToolComputeSimulation" => array('*')
),
'decayingModelMapping' => array(
"viewAssociatedTypes" => array('*'),
"linkAttributeTypeToModel" => array( 'OR' => array('perm_admin', 'perm_decaying'))
),
'communities' => array(
'index' => array(),
'requestAccess' => array(),
'view' => array()
),
'eventBlacklists' => array(
'add' => array(),
'delete' => array(),
'edit' => array(),
'index' => array(),
'massDelete' => array()
),
'eventDelegations' => array(
'acceptDelegation' => array('perm_add'),
'delegateEvent' => array('perm_delegate'),
'deleteDelegation' => array('perm_add'),
'index' => array('*'),
'view' => array('*'),
),
'events' => array(
'add' => array('perm_add'),
'addIOC' => array('perm_add'),
'addTag' => array('perm_tagger'),
'add_misp_export' => array('perm_modify'),
'alert' => array('perm_publish'),
'automation' => array('perm_auth'),
'checkLocks' => array('perm_add'),
'checkPublishedStatus' => array('*'),
'checkuuid' => array('perm_sync'),
'contact' => array('*'),
'csv' => array('*'),
'cullEmptyEvents' => array(),
'delegation_index' => array('*'),
'delete' => array('perm_add'),
'deleteNode' => array('*'),
'dot' => array(),
'downloadExport' => array('*'),
'downloadOpenIOCEvent' => array('*'),
'edit' => array('perm_add'),
'enrichEvent' => array('perm_add'),
'export' => array('*'),
'exportChoice' => array('*'),
'exportModule' => array('*'),
'filterEventIdsForPush' => array('perm_sync'),
'filterEventIndex' => array('*'),
'freeTextImport' => array('perm_add'),
'getEditStrategy' => array('perm_add'),
'getEventInfoById' => array('*'),
'getEventGraphReferences' => array('*'),
'getEventGraphTags' => array('*'),
'getEventGraphGeneric' => array('*'),
'getEventTimeline' => array('*'),
'genDistributionGraph' => array('*'),
'getDistributionGraph' => array('*'),
'getReferenceData' => array('*'),
'getReferences' => array('*'),
'getObjectTemplate' => array('*'),
'handleModuleResults' => array('*'),
'hids' => array('*'),
'index' => array('*'),
'importChoice' => array('*'),
'importModule' => array('*'),
'massDelete' => array('perm_site_admin'),
'merge' => array('perm_modify'),
'nids' => array('*'),
'proposalEventIndex' => array('*'),
'publish' => array('perm_publish'),
'publishSightings' => array('perm_sighting'),
'pushEventToZMQ' => array('perm_publish_zmq'),
'pushEventToKafka' => array('perm_publish_kafka'),
'pushProposals' => array('perm_sync'),
'queryEnrichment' => array('perm_add'),
'removePivot' => array('*'),
'removeTag' => array('perm_tagger'),
'reportValidationIssuesEvents' => array(),
'restSearch' => array('*'),
'saveFreeText' => array('perm_add'),
'stix' => array('*'),
'stix2' => array('*'),
'strposarray' => array(),
'toggleCorrelation' => array('perm_add'),
'unpublish' => array('perm_modify'),
'updateGraph' => array('*'),
'upload_analysis_file' => array('perm_add'),
'upload_sample' => array('AND' => array('perm_auth', 'perm_add')),
'upload_stix' => array('perm_add'),
'view' => array('*'),
'viewEventAttributes' => array('*'),
'viewEventGraph' => array('*'),
'viewGraph' => array('*'),
'viewGalaxyMatrix' => array('*'),
'xml' => array('*')
),
'favouriteTags' => array(
'toggle' => array('*'),
'getToggleField' => array('*')
),
'feeds' => array(
'add' => array(),
'cacheFeeds' => array(),
'compareFeeds' => array('*'),
'delete' => array(),
'disable' => array(),
'edit' => array(),
'enable' => array(),
'feedCoverage' => array('*'),
'fetchFromAllFeeds' => array(),
'fetchFromFeed' => array(),
'fetchSelectedFromFreetextIndex' => array(),
'getEvent' => array(),
'importFeeds' => array(),
'index' => array('*'),
'loadDefaultFeeds' => array('perm_site_admin'),
'previewEvent' => array('*'),
'previewIndex' => array('*'),
'searchCaches' => array('*'),
'toggleSelected' => array('perm_site_admin'),
'view' => array('*'),
),
'galaxies' => array(
'attachCluster' => array('perm_tagger'),
'attachMultipleClusters' => array('perm_tagger'),
'delete' => array(),
'index' => array('*'),
'selectGalaxy' => array('perm_tagger'),
'selectGalaxyNamespace' => array('perm_tagger'),
'selectCluster' => array('perm_tagger'),
'showGalaxies' => array('*'),
'update' => array(),
'view' => array('*'),
'viewGraph' => array('*')
),
'galaxyClusters' => array(
'attachToEvent' => array('perm_tagger'),
'delete' => array('perm_site_admin'),
'detach' => array('perm_tagger'),
'index' => array('*'),
'view' => array('*'),
'viewGalaxyMatrix' => array('*')
),
'galaxyElements' => array(
'index' => array('*')
),
'jobs' => array(
'cache' => array('*'),
'getError' => array(),
'getGenerateCorrelationProgress' => array('*'),
'getProgress' => array('*'),
'index' => array(),
'clearJobs' => array()
),
'logs' => array(
'admin_index' => array('perm_audit'),
'admin_search' => array('perm_audit'),
'event_index' => array('*'),
'maxDateActivity' => array('*'),
'returnDates' => array('*'),
'testForStolenAttributes' => array(),
'pruneUpdateLogs' => array()
),
'modules' => array(
'index' => array('perm_auth'),
'queryEnrichment' => array('perm_auth'),
),
'news' => array(
'add' => array(),
'edit' => array(),
'delete' => array(),
'index' => array('*'),
),
'noticelists' => array(
'delete' => array(),
'enableNoticelist' => array(),
'getToggleField' => array(),
'index' => array('*'),
'toggleEnable' => array(),
'update' => array(),
'view' => array('*')
),
'objects' => array(
'add' => array('perm_add'),
'addValueField' => array('perm_add'),
'delete' => array('perm_add'),
'edit' => array('perm_add'),
'get_row' => array('perm_add'),
'orphanedObjectDiagnostics' => array(),
'editField' => array('perm_add'),
'fetchEditForm' => array('perm_add'),
'fetchViewValue' => array('*'),
'quickAddAttributeForm' => array('perm_add'),
'quickFetchTemplateWithValidObjectAttributes' => array('perm_add'),
'restSearch' => array('*'),
'proposeObjectsFromAttributes' => array('*'),
'groupAttributesIntoObject' => array('perm_add'),
'revise_object' => array('perm_add'),
'view' => array('*'),
),
'objectReferences' => array(
'add' => array('perm_add'),
'delete' => array('perm_add'),
'view' => array('*'),
),
'objectTemplates' => array(
'activate' => array(),
'add' => array('perm_object_template'),
'edit' => array('perm_object_template'),
'delete' => array('perm_object_template'),
'getToggleField' => array(),
'objectChoice' => array('*'),
'objectMetaChoice' => array('perm_add'),
'view' => array('*'),
'viewElements' => array('*'),
'index' => array('*'),
'update' => array('perm_site_admin')
),
'objectTemplateElements' => array(
'viewElements' => array('*')
),
'orgBlacklists' => array(
'add' => array(),
'delete' => array(),
'edit' => array(),
'index' => array(),
),
'organisations' => array(
'admin_add' => array(),
'admin_delete' => array(),
'admin_edit' => array(),
'admin_generateuuid' => array(),
'admin_merge' => array(),
'fetchOrgsForSG' => array('*'),
'fetchSGOrgRow' => array('*'),
'getUUIDs' => array('perm_sync'),
'index' => array('*'),
'landingpage' => array('*'),
'view' => array('*'),
),
'pages' => array(
'display' => array('*'),
),
'posts' => array(
'add' => array('*'),
'delete' => array('*'),
'edit' => array('*'),
'pushMessageToZMQ' => array('perm_site_admin')
),
'regexp' => array(
'admin_add' => array('perm_regexp_access'),
'admin_clean' => array('perm_regexp_access'),
'admin_delete' => array('perm_regexp_access'),
'admin_edit' => array('perm_regexp_access'),
'admin_index' => array('perm_regexp_access'),
'cleanRegexModifiers' => array('perm_regexp_access'),
'index' => array('*'),
),
'restClientHistory' => array(
'delete' => array('*'),
'index' => array('*')
),
'roles' => array(
'admin_add' => array(),
'admin_delete' => array(),
'admin_edit' => array(),
'admin_index' => array('perm_admin'),
'admin_set_default' => array(),
'index' => array('*'),
'view' => array('*'),
),
'servers' => array(
'add' => array(),
'dbSchemaDiagnostic' => array(),
'cache' => array(),
'changePriority' => array(),
'checkout' => array(),
'clearWorkerQueue' => array(),
'createSync' => array('perm_sync'),
'delete' => array(),
'deleteFile' => array(),
'edit' => array(),
'fetchServersForSG' => array('*'),
'filterEventIndex' => array(),
'getApiInfo' => array('*'),
'getGit' => array(),
'getInstanceUUID' => array('perm_sync'),
'getPyMISPVersion' => array('*'),
'getRemoteUser' => array(),
'getSetting' => array(),
'getSubmodulesStatus' => array(),
'getSubmoduleQuickUpdateForm' => array(),
'getWorkers' => array(),
'getVersion' => array('*'),
'import' => array(),
'index' => array(),
'ondemandAction' => array(),
'postTest' => array('perm_sync'),
'previewEvent' => array(),
'previewIndex' => array(),
'pull' => array(),
'purgeSessions' => array(),
'push' => array(),
'releaseUpdateLock' => array(),
'resetRemoteAuthKey' => array(),
'rest' => array('perm_auth'),
'restartDeadWorkers' => array(),
'restartWorkers' => array(),
'serverSettings' => array(),
'serverSettingsEdit' => array(),
'serverSettingsReloadSetting' => array(),
'startWorker' => array(),
'startZeroMQServer' => array(),
'statusZeroMQServer' => array(),
'stopWorker' => array(),
'stopZeroMQServer' => array(),
'testConnection' => array(),
'update' => array(),
'updateJSON' => array(),
'updateProgress' => array(),
'updateSubmodule' => array(),
'uploadFile' => array(),
'viewDeprecatedFunctionUse' => array()
),
'shadowAttributes' => array(
'accept' => array('perm_add'),
'acceptSelected' => array('perm_add'),
'add' => array('perm_add'),
'add_attachment' => array('perm_add'),
'delete' => array('perm_add'),
'discard' => array('perm_add'),
'discardSelected' => array('perm_add'),
'download' => array('*'),
'edit' => array('perm_add'),
'editField' => array('perm_add'),
'fetchEditForm' => array('perm_add'),
'generateCorrelation' => array(),
'getProposalsByUuid' => array('perm_sync'),
'getProposalsByUuidList' => array('perm_sync'),
'index' => array('*'),
'view' => array('*'),
),
'sharingGroups' => array(
'add' => array('perm_sharing_group'),
'addServer' => array('perm_sharing_group'),
'addOrg' => array('perm_sharing_group'),
'delete' => array('perm_sharing_group'),
'edit' => array('perm_sharing_group'),
'index' => array('*'),
'removeServer' => array('perm_sharing_group'),
'removeOrg' => array('perm_sharing_group'),
'view' => array('*'),
),
'sightings' => array(
'add' => array('perm_sighting'),
'restSearch' => array('perm_sighting'),
'advanced' => array('perm_sighting'),
'delete' => array('perm_sighting'),
'index' => array('*'),
'listSightings' => array('*'),
'quickDelete' => array('perm_sighting'),
'viewSightings' => array('*'),
'bulkSaveSightings' => array('OR' => array('perm_sync', 'perm_sighting')),
'quickAdd' => array('perm_sighting')
),
'sightingdb' => array(
'add' => array(),
'edit' => array(),
'delete' => array(),
'index' => array(),
'requestStatus' => array(),
'search' => array()
),
'tagCollections' => array(
'add' => array('perm_tag_editor'),
'addTag' => array('perm_tag_editor'),
'delete' => array('perm_tag_editor'),
'edit' => array('perm_tag_editor'),
'getRow' => array('perm_tag_editor'),
'import' => array('perm_tag_editor'),
'index' => array('*'),
'removeTag' => array('perm_tag_editor'),
'view' => array('*')
),
'tags' => array(
'add' => array('perm_tag_editor'),
'attachTagToObject' => array('perm_tagger'),
'delete' => array(),
'edit' => array(),
'index' => array('*'),
'quickAdd' => array('perm_tag_editor'),
'removeTagFromObject' => array('perm_tagger'),
'search' => array('*'),
'selectTag' => array('perm_tagger'),
'selectTaxonomy' => array('perm_tagger'),
'showEventTag' => array('*'),
'showAttributeTag' => array('*'),
'showTagControllerTag' => array('*'),
'tagStatistics' => array('*'),
'view' => array('*'),
'viewGraph' => array('*'),
'viewTag' => array('*')
),
'tasks' => array(
'index' => array(),
'setTask' => array(),
),
'taxonomies' => array(
'addTag' => array(),
'delete' => array(),
'disable' => array(),
'disableTag' => array(),
'enable' => array(),
'index' => array('*'),
'taxonomyMassConfirmation' => array('perm_tagger'),
'taxonomyMassHide' => array('perm_tagger'),
'taxonomyMassUnhide' => array('perm_tagger'),
'toggleRequired' => array('perm_site_admin'),
'update' => array(),
'view' => array('*'),
'unhideTag' => array('perm_tagger'),
'hideTag' => array('perm_tagger'),
),
'templateElements' => array(
'add' => array('perm_template'),
'delete' => array('perm_template'),
'edit' => array('perm_template'),
'index' => array('*'),
'templateElementAddChoices' => array('perm_template'),
),
'templates' => array(
'add' => array('perm_template'),
'delete' => array('perm_template'),
'deleteTemporaryFile' => array('perm_add'),
'edit' => array('perm_template'),
'index' => array('*'),
'populateEventFromTemplate' => array('perm_add'),
'saveElementSorting' => array('perm_template'),
'submitEventPopulation' => array('perm_add'),
'templateChoices' => array('*'),
'uploadFile' => array('*'),
'view' => array('*'),
),
'threads' => array(
'index' => array('*'),
'view' => array('*'),
'viewEvent' => array('*'),
),
'users' => array(
'acceptRegistrations' => array('perm_site_admin'),
'admin_add' => array('perm_admin'),
'admin_delete' => array('perm_admin'),
'admin_edit' => array('perm_admin'),
'admin_email' => array('perm_admin'),
'admin_filterUserIndex' => array('perm_admin'),
'admin_index' => array('perm_admin'),
'admin_monitor' => array('perm_site_admin'),
'admin_quickEmail' => array('perm_admin'),
'admin_view' => array('perm_admin'),
'attributehistogram' => array('*'),
'change_pw' => array('*'),
'checkAndCorrectPgps' => array(),
'checkIfLoggedIn' => array('*'),
'dashboard' => array('*'),
'delete' => array('perm_admin'),
'discardRegistrations' => array('perm_site_admin'),
'downloadTerms' => array('*'),
'edit' => array('*'),
'email_otp' => array('*'),
'searchGpgKey' => array('*'),
'fetchGpgKey' => array('*'),
'histogram' => array('*'),
'initiatePasswordReset' => array('perm_admin'),
'login' => array('*'),
'logout' => array('*'),
'register' => array('*'),
'registrations' => array('perm_site_admin'),
'resetAllSyncAuthKeys' => array(),
'resetauthkey' => array('*'),
'request_API' => array('*'),
'routeafterlogin' => array('*'),
'statistics' => array('*'),
'tagStatisticsGraph' => array('*'),
'terms' => array('*'),
'updateLoginTime' => array('*'),
'verifyCertificate' => array(),
'verifyGPG' => array(),
'view' => array('*'),
),
'userSettings' => array(
'index' => array('*'),
'view' => array('*'),
'setSetting' => array('*'),
'getSetting' => array('*'),
'delete' => array('*'),
'setHomePage' => array('*')
),
'warninglists' => array(
'checkValue' => array('perm_auth'),
'delete' => array(),
'enableWarninglist' => array(),
'getToggleField' => array(),
'index' => array('*'),
'toggleEnable' => array(),
'update' => array(),
'view' => array('*')
),
'whitelists' => array(
'admin_add' => array('perm_regexp_access'),
'admin_delete' => array('perm_regexp_access'),
'admin_edit' => array('perm_regexp_access'),
'admin_index' => array('perm_regexp_access'),
'index' => array('*'),
),
'eventGraph' => array(
'view' => array('*'),
'add' => array('perm_add'),
'delete' => array('perm_modify'),
)
private $aclList = array(
'Pages' => [
'display' => ['*']
],
'Users' => [
'add' => ['perm_admin'],
'delete' => ['perm_admin'],
'edit' => ['*'],
'index' => ['perm_admin'],
'login' => ['*'],
'logout' => ['*'],
'view' => ['*']
]
);
private function __checkLoggedActions($user, $controller, $action)
@ -681,7 +98,7 @@ class ACLComponent extends Component
}
}
if ($hit) {
$this->Log = ClassRegistry::init('Log');
$this->Log = TableRegistry::get('Log');
$this->Log->create();
$this->Log->save(array(
'org' => 'SYSTEM',
@ -698,43 +115,58 @@ class ACLComponent extends Component
}
}
public function setUser(User $user): void
{
$this->user = $user;
}
public function getUser(): User
{
return $this->user;
}
/*
* By default nothing besides the login is public. If configured, override the list with the additional interfaces
*/
public function setPublicInterfaces(): void
{
$this->Authentication->allowUnauthenticated(['login']);
}
// The check works like this:
// If the user is a site admin, return true
// If the requested action has an OR-d list, iterate through the list. If any of the permissions are set for the user, return true
// If the requested action has an AND-ed list, iterate through the list. If any of the permissions for the user are not set, turn the check to false. Otherwise return true.
// If the requested action has a permission, check if the user's role has it flagged. If yes, return true
// If we fall through all of the checks, return an exception.
public function checkAccess($user, $controller, $action, $soft = false)
public function checkAccess(bool $soft = false): bool
{
$controller = lcfirst(Inflector::camelize($controller));
$action = strtolower($action);
$aclList = $this->__aclList;
foreach ($aclList as $k => $v) {
$aclList[$k] = array_change_key_case($v);
}
$this->__checkLoggedActions($user, $controller, $action);
if ($user['Role']['perm_site_admin']) {
$controller = $this->request->getParam('controller');
$action = $this->request->getParam('action');
if (empty($this->user)) {
// we have to be in a publically allowed scope otherwise the Auth component will kick us out anyway.
return true;
}
if (!isset($aclList[$controller])) {
return $this->__error(404, 'Invalid controller.', $soft);
}
if ($user['Role']['perm_site_admin']) {
if (!empty($this->user->role->perm_admin)) {
return true;
}
if (isset($aclList[$controller][$action]) && !empty($aclList[$controller][$action])) {
if (in_array('*', $aclList[$controller][$action])) {
//$this->__checkLoggedActions($user, $controller, $action);
if (!isset($this->aclList[$controller])) {
return $this->__error(404, __('Invalid controller.'), $soft);
}
if (isset($this->aclList[$controller][$action]) && !empty($this->aclList[$controller][$action])) {
if (in_array('*', $this->aclList[$controller][$action])) {
return true;
}
if (isset($aclList[$controller][$action]['OR'])) {
foreach ($aclList[$controller][$action]['OR'] as $permission) {
if (isset($this->aclList[$controller][$action]['OR'])) {
foreach ($this->aclList[$controller][$action]['OR'] as $permission) {
if ($user['Role'][$permission]) {
return true;
}
}
} elseif (isset($aclList[$controller][$action]['AND'])) {
} elseif (isset($this->aclList[$controller][$action]['AND'])) {
$allConditionsMet = true;
foreach ($aclList[$controller][$action]['AND'] as $permission) {
foreach ($this->aclList[$controller][$action]['AND'] as $permission) {
if (!$user['Role'][$permission]) {
$allConditionsMet = false;
}
@ -742,8 +174,6 @@ class ACLComponent extends Component
if ($allConditionsMet) {
return true;
}
} elseif ($user['Role'][$aclList[$controller][$action][0]]) {
return true;
}
}
return $this->__error(403, 'You do not have permission to use this functionality.', $soft);
@ -770,13 +200,13 @@ class ACLComponent extends Component
$functionFinder = '/function[\s\n]+(\S+)[\s\n]*\(/';
$dir = new Folder(APP . 'Controller');
$files = $dir->find('.*\.php');
$results = array();
$results = [];
foreach ($files as $file) {
$controllerName = lcfirst(str_replace('Controller.php', "", $file));
if ($controllerName === 'app') {
$controllerName = '*';
}
$functionArray = array();
$functionArray = [];
$fileContents = file_get_contents(APP . 'Controller' . DS . $file);
$fileContents = preg_replace('/\/\*[^\*]+?\*\//', '', $fileContents);
preg_match_all($functionFinder, $fileContents, $functionArray);
@ -799,7 +229,7 @@ class ACLComponent extends Component
public function findMissingFunctionNames($content = false)
{
$results = $this->__findAllFunctions();
$missing = array();
$missing = [];
foreach ($results as $controller => $functions) {
foreach ($functions as $function) {
if (!isset($this->__aclList[$controller])
@ -813,9 +243,9 @@ class ACLComponent extends Component
public function printRoleAccess($content = false)
{
$results = array();
$this->Role = ClassRegistry::init('Role');
$conditions = array();
$results = [];
$this->Role = TableRegistry::get('Role');
$conditions = [];
if (is_numeric($content)) {
$conditions = array('Role.id' => $content);
}
@ -835,7 +265,7 @@ class ACLComponent extends Component
private function __checkRoleAccess($role)
{
$result = array();
$result = [];
foreach ($this->__aclList as $controller => $actions) {
$controllerNames = Inflector::variable($controller) == Inflector::underscore($controller) ? array(Inflector::variable($controller)) : array(Inflector::variable($controller), Inflector::underscore($controller));
foreach ($controllerNames as $controllerName) {

View File

@ -38,8 +38,11 @@ class UsersController extends AppController
$this->set('metaGroup', $this->isAdmin ? 'Administration' : 'Cerebrate');
}
public function view($id)
public function view($id = false)
{
if (empty($id) || empty($this->ACL->getUser()['role']['perm_admin'])) {
$id = $this->ACL->getUser()['id'];
}
$this->CRUD->view($id, [
'contain' => ['Individuals' => ['Alignments' => 'Organisations'], 'Roles']
]);
@ -49,9 +52,16 @@ class UsersController extends AppController
$this->set('metaGroup', $this->isAdmin ? 'Administration' : 'Cerebrate');
}
public function edit($id)
public function edit($id = false)
{
$this->CRUD->edit($id);
if (empty($id) || empty($this->ACL->getUser()['role']['perm_admin'])) {
$id = $this->ACL->getUser()['id'];
}
$this->CRUD->edit($id, [
'get' => [
'fields' => ['id', 'individual_id', 'role_id', 'username', 'disabled']
]
]);
if ($this->ParamHandler->isRest()) {
return $this->restResponsePayload;
}
@ -76,4 +86,28 @@ class UsersController extends AppController
}
$this->set('metaGroup', $this->isAdmin ? 'Administration' : 'Cerebrate');
}
public function login()
{
$result = $this->Authentication->getResult();
// If the user is logged in send them away.
if ($result->isValid()) {
$target = $this->Authentication->getLoginRedirect() ?? '/instance/home';
return $this->redirect($target);
}
if ($this->request->is('post') && !$result->isValid()) {
$this->Flash->error(__('Invalid username or password'));
}
$this->viewBuilder()->setLayout('login');
}
public function logout()
{
$result = $this->Authentication->getResult();
if ($result->isValid()) {
$this->Authentication->logout();
$this->Flash->success(__('Goodbye.'));
return $this->redirect(['controller' => 'Users', 'action' => 'login']);
}
}
}

View File

@ -4,8 +4,14 @@ namespace App\Model\Entity;
use App\Model\Entity\AppModel;
use Cake\ORM\Entity;
use Authentication\PasswordHasher\DefaultPasswordHasher;
class User extends AppModel
{
protected function _setPassword(string $password) : ?string
{
if (strlen($password) > 0) {
return (new DefaultPasswordHasher())->hash($password);
}
}
}

View File

@ -5,6 +5,7 @@ namespace App\Model\Table;
use App\Model\Table\AppTable;
use Cake\ORM\Table;
use Cake\Validation\Validator;
use Cake\ORM\RulesChecker;
class UsersTable extends AppTable
{
@ -26,7 +27,7 @@ class UsersTable extends AppTable
'cascadeCallbacks' => false
]
);
$this->setDisplayField('id');
$this->setDisplayField('username');
}
public function validationDefault(Validator $validator): Validator
@ -35,4 +36,9 @@ class UsersTable extends AppTable
->requirePresence(['password'], 'create');
return $validator;
}
public function buildRules(RulesChecker $rules): RulesChecker
{
return $rules;
}
}

View File

@ -11,10 +11,7 @@
'options' => $dropdownData['individual']
],
[
'field' => 'role_id',
'type' => 'dropdown',
'label' => __('Role'),
'options' => $dropdownData['role']
'field' => 'username'
],
[
'field' => 'password',
@ -24,6 +21,12 @@
'field' => 'confirm_password',
'label' => __('Confirm Password')
],
[
'field' => 'role_id',
'type' => 'dropdown',
'label' => __('Role'),
'options' => $dropdownData['role']
],
[
'field' => 'disabled',
'type' => 'checkbox',

View File

@ -5,6 +5,17 @@ echo $this->element('genericElements/IndexTable/index_table', [
'top_bar' => [
'pull' => 'right',
'children' => [
[
'type' => 'simple',
'children' => [
'data' => [
'type' => 'simple',
'text' => __('Add User'),
'class' => 'btn btn-primary',
'popover_url' => '/users/add'
]
]
],
[
'type' => 'search',
'button' => __('Filter'),
@ -20,6 +31,11 @@ echo $this->element('genericElements/IndexTable/index_table', [
'sort' => 'id',
'data_path' => 'id',
],
[
'name' => __('Username'),
'sort' => 'username',
'data_path' => 'username',
],
[
'name' => __('Email'),
'sort' => 'individual.email',
@ -55,8 +71,8 @@ echo $this->element('genericElements/IndexTable/index_table', [
'icon' => 'eye'
],
[
'url' => '/users/edit',
'url_params_data_paths' => ['id'],
'onclick' => 'populateAndLoadModal(\'/users/edit/[onclick_params_data_path]\');',
'onclick_params_data_path' => 'id',
'icon' => 'edit'
],
[