2019-09-25 11:50:54 +02:00
< ? php
/*
*
* Feature developed as part of a training given by CIRCL in Luxembourg on 26 / 09 / 2019
* Verbose comments for educational purposes only
*
*/
App :: uses ( 'AppController' , 'Controller' );
class UserSettingsController extends AppController
{
public $components = array ( 'Session' , 'RequestHandler' );
public $paginate = array (
'limit' => 60 ,
'maxLimit' => 9999 ,
'order' => array (
'UserSetting.id' => 'DESC'
),
'contain' => array (
'User.id' ,
'User.email'
)
);
2020-03-01 18:05:21 +01:00
public function beforeFilter ()
{
parent :: beforeFilter ();
$this -> Security -> unlockedActions = array ( 'setHomePage' );
}
2019-09-25 11:50:54 +02:00
public function index ()
{
$filterData = array (
'request' => $this -> request ,
'paramArray' => array ( 'setting' , 'user_id' , 'sort' , 'direction' , 'page' , 'limit' ),
'named_params' => $this -> params [ 'named' ]
);
$exception = false ;
$filters = $this -> _harvestParameters ( $filterData , $exception );
$conditions = array ();
if ( ! empty ( $filters [ 'setting' ])) {
$conditions [ 'AND' ][] = array (
'setting' => $filters [ 'setting' ]
);
}
if ( ! empty ( $filters [ 'user_id' ])) {
if ( $filters [ 'user_id' ] === 'all' ) {
$context = 'all' ;
} else if ( $filters [ 'user_id' ] === 'me' ) {
$conditions [ 'AND' ][] = array (
'user_id' => $this -> Auth -> user ( 'id' )
);
$context = 'me' ;
} else if ( $filters [ 'user_id' ] === 'org' ) {
$conditions [ 'AND' ][] = array (
'user_id' => $this -> UserSetting -> User -> find (
'list' , array (
'conditions' => array (
'User.org_id' => $this -> Auth -> user ( 'org_id' )
),
'fields' => array (
'User.id' , 'User.id'
)
)
)
);
$context = 'org' ;
} else {
$conditions [ 'AND' ][] = array (
'user_id' => $filters [ 'user_id' ]
);
}
}
if ( ! $this -> _isSiteAdmin ()) {
if ( $this -> _isAdmin ()) {
$conditions [ 'AND' ][] = array (
'UserSetting.user_id' => $this -> UserSetting -> User -> find (
'list' , array (
'conditions' => array (
'User.org_id' => $this -> Auth -> user ( 'org_id' )
),
'fields' => array (
'User.id' , 'User.id'
)
)
)
);
} else {
$conditions [ 'AND' ][] = array (
'UserSetting.user_id' => $this -> Auth -> user ( 'id' )
);
}
}
if ( $this -> _isRest ()) {
$params = array (
'conditions' => $conditions
);
if ( ! empty ( $filters [ 'page' ])) {
$params [ 'page' ] = $filters [ 'page' ];
$params [ 'limit' ] = $this -> paginate [ 'limit' ];
}
if ( ! empty ( $filters [ 'limit' ])) {
$params [ 'limit' ] = $filters [ 'limit' ];
}
$userSettings = $this -> UserSetting -> find ( 'all' , $params );
return $this -> RestResponse -> viewData ( $userSettings , $this -> response -> type ());
} else {
$this -> paginate [ 'conditions' ] = $conditions ;
2019-10-10 11:58:26 +02:00
$data = $this -> paginate ();
foreach ( $data as $k => $v ) {
if ( ! empty ( $this -> UserSetting -> validSettings [ $v [ 'UserSetting' ][ 'setting' ]])) {
$data [ $k ][ 'UserSetting' ][ 'restricted' ] = empty ( $this -> UserSetting -> validSettings [ $v [ 'UserSetting' ][ 'setting' ]][ 'restricted' ]) ? '' : $this -> UserSetting -> validSettings [ $v [ 'UserSetting' ][ 'setting' ]][ 'restricted' ];
} else {
$data [ $k ][ 'UserSetting' ][ 'restricted' ] = array ();
}
}
$this -> set ( 'data' , $data );
2019-09-25 11:50:54 +02:00
$this -> set ( 'context' , empty ( $context ) ? 'null' : $context );
}
}
public function view ( $id )
{
// check if the ID is valid and whether a user setting with the given ID exists
if ( empty ( $id ) || ! is_numeric ( $id )) {
throw new InvalidArgumentException ( __ ( 'Invalid ID passed.' ));
}
$userSetting = $this -> UserSetting -> find ( 'first' , array (
'recursive' => - 1 ,
'conditions' => array (
'UserSetting.id' => $id
),
'contain' => array ( 'User.id' , 'User.org_id' )
));
2019-09-29 20:21:35 +02:00
if ( empty ( $userSetting )) {
throw new NotFoundException ( __ ( 'Invalid user setting.' ));
}
2019-09-25 11:50:54 +02:00
$checkAccess = $this -> UserSetting -> checkAccess ( $this -> Auth -> user (), $userSetting );
2019-09-29 20:21:35 +02:00
if ( ! $checkAccess ) {
2019-09-25 11:50:54 +02:00
throw new NotFoundException ( __ ( 'Invalid user setting.' ));
}
if ( $this -> _isRest ()) {
unset ( $userSetting [ 'User' ]);
return $this -> RestResponse -> viewData ( $userSetting , $this -> response -> type ());
} else {
$this -> set ( $data , $userSetting );
}
}
public function setSetting ( $user_id = false , $setting = false )
{
2019-10-10 11:58:26 +02:00
if ( ! empty ( $setting )) {
if ( ! $this -> UserSetting -> checkSettingValidity ( $setting )) {
throw new MethodNotAllowedException ( __ ( 'Invalid setting.' ));
}
$settingPermCheck = $this -> UserSetting -> checkSettingAccess ( $this -> Auth -> user (), $setting );
if ( $settingPermCheck !== true ) {
throw new MethodNotAllowedException ( __ ( 'This setting is restricted and requires the following permission(s): %s' , $settingPermCheck ));
}
}
2019-09-25 11:50:54 +02:00
// handle POST requests
if ( $this -> request -> is ( 'post' )) {
// massage the request to allow for unencapsulated POST requests via the API
// {"key": "value"} instead of {"UserSetting": {"key": "value"}}
if ( empty ( $this -> request -> data [ 'UserSetting' ])) {
$this -> request -> data = array ( 'UserSetting' => $this -> request -> data );
}
if ( ! empty ( $user_id )) {
$this -> request -> data [ 'UserSetting' ][ 'user_id' ] = $user_id ;
}
if ( ! empty ( $setting )) {
$this -> request -> data [ 'UserSetting' ][ 'setting' ] = $setting ;
}
// force our user's ID as the user ID in all cases
$userSetting = array (
'user_id' => $this -> Auth -> user ( 'id' )
);
2020-03-01 18:05:21 +01:00
$result = $this -> UserSetting -> setSetting ( $this -> Auth -> user (), $this -> request -> data );
2019-09-25 11:50:54 +02:00
if ( $result ) {
// if we've managed to save our setting
if ( $this -> _isRest ()) {
// if we are dealing with an API request
$userSetting = $this -> UserSetting -> find ( 'first' , array (
'recursive' => - 1 ,
'conditions' => array ( 'UserSetting.id' => $this -> UserSetting -> id )
));
return $this -> RestResponse -> viewData ( $userSetting , $this -> response -> type ());
} else {
// if we are dealing with a UI request, redirect the user to the user view with the proper flash message
$this -> Flash -> success ( __ ( 'Setting saved.' ));
$this -> redirect ( array ( 'controller' => 'user_settings' , 'action' => 'index' , $this -> Auth -> User ( 'id' )));
}
} else {
// if we've failed saving our setting
if ( $this -> _isRest ()) {
// if we are dealing with an API request
return $this -> RestResponse -> saveFailResponse ( 'UserSettings' , 'add' , false , $this -> UserSetting -> validationErrors , $this -> response -> type ());
} else {
/*
* if we are dealing with a UI request , simply set an error in a flash message
* and render the view of this endpoint , pre - populated with the submitted values .
*/
$this -> Flash -> error ( __ ( 'Setting could not be saved.' ));
}
}
}
if ( $this -> _isRest ()) {
// GET request via the API should describe the endpoint
2019-09-29 20:21:35 +02:00
return $this -> RestResponse -> describe ( 'UserSettings' , 'setSetting' , false , $this -> response -> type ());
2019-09-25 11:50:54 +02:00
} else {
// load the valid settings from the model
$validSettings = $this -> UserSetting -> validSettings ;
if ( $this -> _isSiteAdmin ()) {
$users = $this -> UserSetting -> User -> find ( 'list' , array (
'recursive' => - 1 ,
'fields' => array ( 'User.id' , 'User.email' )
));
} else if ( $this -> _isAdmin ()) {
$users = $this -> UserSetting -> User -> find ( 'list' , array (
'recursive' => - 1 ,
'conditions' => array ( 'User.org_id' => $this -> Auth -> user ( 'org_id' )),
'fields' => array ( 'User.id' , 'User.email' )
));
} else {
$users = array ( $this -> Auth -> user ( 'id' ) => $this -> Auth -> user ( 'email' ));
}
2019-09-29 20:21:35 +02:00
if ( ! empty ( $user_id ) && $this -> request -> is ( 'get' )) {
$this -> request -> data [ 'UserSetting' ][ 'user_id' ] = $user_id ;
}
2019-10-10 11:58:26 +02:00
$this -> set ( 'setting' , $setting );
2019-09-25 11:50:54 +02:00
$this -> set ( 'users' , $users );
$this -> set ( 'validSettings' , $validSettings );
}
}
public function getSetting ( $user_id , $setting )
{
if ( ! $this -> UserSetting -> checkSettingValidity ( $setting )) {
throw new MethodNotAllowedException ( __ ( 'Invalid setting.' ));
}
$userSetting = $this -> UserSetting -> find ( 'first' , array (
'recursive' => - 1 ,
'conditions' => array (
'UserSetting.user_id' => $user_id ,
'UserSetting.setting' => $setting
),
'contain' => array ( 'User.id' , 'User.org_id' )
));
2019-09-29 20:21:35 +02:00
$checkAccess = $this -> UserSetting -> checkAccess ( $this -> Auth -> user (), $userSetting , $user_id );
2019-09-25 11:50:54 +02:00
if ( empty ( $checkAccess )) {
throw new MethodNotAllowedException ( __ ( 'Invalid setting.' ));
}
if ( ! empty ( $userSetting )) {
$userSetting = json_encode ( $userSetting [ 'UserSetting' ][ 'value' ]);
} else {
$userSetting = '[]' ;
}
return $this -> RestResponse -> viewData ( $userSetting , $this -> response -> type (), false , true );
}
public function delete ( $id = false )
{
if ( $this -> request -> is ( 'get' ) && $this -> _isRest ()) {
/*
* GET request via the API should describe the endpoint
* Unlike with the add () endpoint , we want to run this check before doing anything else ,
* in order to allow us to reach this endpoint without passing a valid ID
*/
return $this -> RestResponse -> describe ( 'UserSettings' , 'delete' , false , $this -> response -> type ());
}
// check if the ID is valid and whether a user setting with the given ID exists
if ( empty ( $id ) || ! is_numeric ( $id )) {
throw new InvalidArgumentException ( __ ( 'Invalid ID passed.' ));
}
$userSetting = $this -> UserSetting -> find ( 'first' , array (
'recursive' => - 1 ,
'conditions' => array (
'UserSetting.id' => $id
),
'contain' => array ( 'User.id' , 'User.org_id' )
));
2019-09-29 20:21:35 +02:00
if ( empty ( $userSetting )) {
throw new NotFoundException ( __ ( 'Invalid user setting.' ));
}
2019-09-25 11:50:54 +02:00
$checkAccess = $this -> UserSetting -> checkAccess ( $this -> Auth -> user (), $userSetting );
2019-09-29 20:21:35 +02:00
if ( ! $checkAccess ) {
2019-09-25 11:50:54 +02:00
throw new NotFoundException ( __ ( 'Invalid user setting.' ));
}
2019-10-10 11:58:26 +02:00
$settingPermCheck = $this -> UserSetting -> checkSettingAccess ( $this -> Auth -> user (), $userSetting [ 'UserSetting' ][ 'setting' ]);
if ( $settingPermCheck !== true ) {
throw new MethodNotAllowedException ( __ ( 'This setting is restricted and requires the following permission(s): %s' , $settingPermCheck ));
}
2019-09-25 11:50:54 +02:00
if ( $this -> request -> is ( 'post' ) || $this -> request -> is ( 'delete' )) {
// Delete the setting that we were after.
$result = $this -> UserSetting -> delete ( $userSetting [ 'UserSetting' ][ 'id' ]);
if ( $result ) {
// set the response for both the UI and API
$message = __ ( 'Setting deleted.' );
if ( $this -> _isRest ()) {
return $this -> RestResponse -> saveSuccessResponse ( 'UserSettings' , 'delete' , $id , $this -> response -> type (), $message );
} else {
$this -> Flash -> success ( $message );
}
} else {
// set the response for both the UI and API
$message = __ ( 'Setting could not be deleted.' );
if ( $this -> _isRest ()) {
return $this -> RestResponse -> saveFailResponse ( 'UserSettings' , 'delete' , $id , $message , $this -> response -> type ());
} else {
$this -> Flash -> error ( $message );
}
}
/*
* The API responses stopped executing this function and returned a serialised response to the user .
* For UI users , redirect to where they issued the request from .
*/
$this -> redirect ( $this -> referer ());
} else {
throw new MethodNotAllowedException ( __ ( 'Expecting POST or DELETE request.' ));
}
}
2020-03-01 18:05:21 +01:00
public function setHomePage ()
{
if ( ! $this -> request -> is ( 'post' )) {
throw new MethodNotAllowedException ( __ ( 'This endpoint only aaccepts POST requests.' ));
}
if ( empty ( $this -> request -> data [ 'path' ])) {
$this -> request -> data = array ( 'path' => $this -> request -> data );
}
if ( empty ( $this -> request -> data [ 'path' ])) {
throw new InvalidArgumentException ( __ ( 'No path POSTed.' ));
}
$setting = array (
'UserSetting' => array (
'user_id' => $this -> Auth -> user ( 'id' ),
'setting' => 'homepage' ,
'value' => json_encode ( array ( 'path' => $this -> request -> data [ 'path' ]))
)
);
$result = $this -> UserSetting -> setSetting ( $this -> Auth -> user (), $setting );
return $this -> RestResponse -> saveSuccessResponse ( 'UserSettings' , 'setHomePage' , false , $this -> response -> type (), 'Homepage set to ' . $this -> request -> data [ 'path' ]);
}
2019-09-25 11:50:54 +02:00
}