I am struggling to create an access object to sections stored in the Database. This is a skellington of the process, this contains static data until I can get the principle working.
class User {
const IS_ADMIN = 1;
const IS_MODERATOR = 2;
const IS_MEMBER = 4;
}
This class will auto-load data from the database eventually but for the time being, this class has default values.
class Scope {
private $priv = [];
public function __construct() {
$this->priv = [1];
}
public function getPrivilidges() {
return $this->priv;
}
}
This is where it messes up, I can tell that the second and third conditions cannot be met if the first fails, how can I stop this?
class Priverlidges {
public function canView($type, Scope $scope) {
if($type & User::IS_ADMIN) {
foreach($scope->getPrivilidges() as $p) {
if($p == User::IS_ADMIN) continue;
return false;
}
return true;
}
if($type & User::IS_MODERATOR) {
foreach($scope->getPrivilidges() as $p) {
if($p == User::IS_MODERATOR) continue;
return false;
}
return true;
}
if($type & User::IS_MEMBER) {
foreach($scope->getPrivilidges() as $p) {
if($p == User::IS_MEMBER) continue;
return false;
}
return true;
}
}
}
Example usage which works fine when the default value of the priverlidge is 1:
echo (int)(new Priverlidges)->canView(User::IS_ADMIN, new Scope());
Example usage which works fine when the default value of the priverlidge is 2:
echo (int)(new Priverlidges)->canView(User::IS_MODERATOR | User::IS_ADMIN, new Scope()); // it returns false at the first condition
Can anyone help me with when to return true or false? Thanks in advance.
P.S - Users can be both Mods and Admins
EDIT: I have tried to use in_array() and still am unsure when to return the value true or false because it get's overwrite if the second method runs.
I figured it out. First, check the user is not already authenticated using a placeholder ($this->_state). Then check the type of user and check it is inside the scope.
class Priverlidges {
private $_state = false;
public function canView($type, Scope $scope) {
if(!$this->_state && $type & User::IS_ADMIN && in_array(User::IS_ADMIN, $scope->getPrivilidges())) {
$this->_state = true;
}
if(!$this->_state && $type & User::IS_MODERATOR && in_array(User::IS_MODERATOR, $scope->getPrivilidges())) {
$this->_state = true;
}
if(!$this->_state && $type & User::IS_MEMBER && in_array($scope->getPrivilidges(), User::IS_MEMBER)) {
$this->_state = true;
}
return $this->_state;
}
}
Related
I'm working on a Silverstripe 4.3.1 project which has an object with an owner member attached via $has_one:
class Object extends DataObject
{
private static $has_one = [
'Member' => Member::class,
];
We want to limit the ability to view/ edit the object to Admins & the owner member.
Here is the code we've used:
public function canView($member = null)
{
return Permission::check('ADMIN') or
$this->Member()->ID === Security::getCurrentUser()->ID or
$this->Member()->ID === $member->ID;
}
public function canEdit($member = null)
{
return Permission::check('ADMIN') or
$this->Member()->ID === Security::getCurrentUser()->ID or
$this->Member()->ID === $member->ID;
}
From what I can tell this used to work, but recent framework upgrades or code changes have broken it.
We are currently getting the following PHP error:
Trying to get property of non-object on the lines containing $this->Member()->ID
Can anyone point me in the right direction for how to fix these errors?
It may be that some Object instances do no have a Member set. In those cases calling this->Member()->ID will error as Member() returns null.
First we should check if $this->Member() is for the Object. If it is not we can return false.
public function canView($member = null)
{
if (Permission::check('ADMIN')) {
return true;
}
if (!$this || !$this->exists()) {
return false;
}
if (!$this->Member() || !$this->Member()->exists()) {
return false;
}
if ($this->Member()->ID === $member->ID) {
return true;
}
if ($this->Member()->ID === Security::getCurrentUser()->ID) {
return true;
}
return false;
}
public function canEdit($member = null)
{
if (Permission::check('ADMIN')) {
return true;
}
if (!$this || !$this->exists()) {
return false;
}
if (!$this->Member() || !$this->Member()->exists()) {
return false;
}
if ($this->Member()->ID === $member->ID) {
return true;
}
if ($this->Member()->ID === Security::getCurrentUser()->ID) {
return true;
}
return false;
}
Hello im testing a method which uses this function, that is not in any class. It needs to be as it is without the class because this is in wordpress. I need to mock this function, i declared it twice once it will return true and second time it will return false, but it gave me an error with redeclaration. What should i do to mock this method twice?
function wcs_order_contains_subscription() {
return false;
}
//testing stuff
function wcs_order_contains_subscription() {
return true;
}
//test another stuff
EDIT:
for ($i = 0; $i < 2; $i++) {
if ($i == 0) {
function wcs_order_contains_subscription() {
return false;
}
var_dump($gateway->process_payment($order_id));
} else {
function wcs_order_contains_subscription() {
return true;
}
var_dump($gateway->process_payment($order_id));
exit();
}
}
I want to check whether a user has permission to an employee.
function hasEmployeePermission($employeeID, $userKey)
{
$usersID = DB::table('users')->where('key', $userKey)->value('id');
if($userID != null) {
$employeeID = DB::table('employees')->where('user_id', $userID)->value('id');
if($mployeeID != null)
return true;
else
return false;
}
return false;
}
I want the return value to be more expressive like throwing a exception. I think throwing an exception in logical error is not a best practice. I want t know how to modify the code to return an error.
Create a simple error class.
Class myError{
public $error = true;
public $message = null;
function __construct($error,$message) {
$this->error = $error;
$this->message = $message;
}
}
then you can do something like this,
if($mployeeID != null)
return new myError(true,"no permission");
else
return new myError(false,"has permission");
There could be a lot more functionality added to the class, e.g. logging the error somewhere or things like that
If you want to know why your function failed and in which case, I would recommend using an enum.
Here is an example :
abstract class EmployeeErrors
{
const WrongID = 1;
const NoPermissions = 2;
// etc.
}
function hasEmployeePermission($employeeID, $userKey)
{
$usersID = DB::table('users')->where('key', $userKey)->value('id');
if($userID != null) {
$employeeID = DB::table('employees')->where('user_id', $userID)->value('id');
if($mployeeID != null)
return 0;
else
if ($userKey == null)
return EmployeeErrors::WrongKey;
else ...
}
return EmployeeErrors::WrongID;
}
I need opinion about using session with php. I'm useing session to store data. For instance - configuration:
First I'm loading data from config.ini to $_SESSION['config']
Then I'm using custom session class to get specific data from $_SESSION['config'][$key];
This is config function:
public static function load_config($process_sections = FALSE)
{
$array = parse_ini_file(CONFIG . DS . 'config.ini', $process_sections);
if ($array)
{
$_SESSION['configuration'] = $array;
return TRUE;
}
else
{
$_SESSION['configuration'] = array();
return FALSE;
}
}
function config($key, $default = NULL)
{
if (isset($_SESSION['configuration']))
{
if (isset($_SESSION['configuration'][$key]))
{
return $_SESSION['configuration'][$key];
}
else
{
return $default;
}
}
}
That same is with user object. I'm getting user data not from DB, but API, and storing it in $_SESSION['user']. When user object is constructs, I'm attributing all properties just from $_SESSION['user'][...], for instance:
public function __construct()
{
parent::__construct();
$this->initUser();
}
private function initUser()
{
if (Session::is('user'))
{
return $this->setUserData(Session::get('user'));
}
else
{
return FALSE;
}
}
private function setUserData($data)
{
foreach ($data as $key => $value)
{
if(property_exists($this->_name, $key))
{
$this->{$key} = $value;
}
}
return TRUE;
}
Properties are defined in class. I'm doing it just on time, when object is constructing. Is that right practice? It's working very good for me but I doubt if my method overolads server.
Ok so I currently have this Controller which basically retrieves a Model and does some calculation.
Original code has tonnes of calculation but this is a trimmed down version for simplicity.
I wanted to move all logic to the Model and have built the code below it so far but can not figure out how to pass the custom messages to the Controller.
I am a beginner in Laravel so trying to achieve this in an easy to understand way so I can maintain it and managed to get the code below working but without custom error messages being passed onto the Controller.
Can you give me an example code of how you are passing custom error messages to controller
This is the original code in controller.
Controller
public function getDetail()
{
$request = Model::where('id','=',8)->first();
if($request)
{
if($request->number >= 5)
{
return Redirect::back()->withMessage('You have 5 or more');
}
if($request->number > 0 && $request->number < 5)
{
return Redirect::back()->withMessage('You have between 1 and 4');
}
if($request->number <= 0)
{
return Redirect::back()->withErrors('You do not have enough points');
}
}
else
{
return Redirect::back()->withErrors('No details found');
}
}
This is the new code I tried to build to move logic to model but could not figure out how to pass the custom error messages along?
Model
Class Profile
{
private $model
function __construct()
{
$this->model = Model::where('id','=',8)->first();
}
public function Notification()
{
if($this->model->number >=5)
{
return true;
}
if($this->model->number > 0 && $this->model->number < 5)
{
return true;
}
if($this->model->number <=0)
{
return false;
}
}
}
Controller
public function getDetail()
{
$request = new Profile;
$result = $request->Notification();
if($result)
{
return Redirect::back()->withMessage(????????);
}
else
{
return Redirect::back()->withErrors(????????);
}
}
Just return the message from the Model function and use it in the controller to return like shown below.
Model function
public function Notification()
{
$returnArray = array();
if($this->model->number >=5)
{
$returnArray['isMessage'] = true;
$returnArray['message'] = "You have 5 or more";
}
if($this->model->number > 0 && $this->model->number < 5)
{
$returnArray['isMessage'] = true;
$returnArray['message'] = "You have between 1 and 4";
}
if($this->model->number <=0)
{
$returnArray['isError'] = true;
$returnArray['error'] = "You do not have enough points";
}
return $returnArray;
}
Controller function
public function getDetail()
{
$request = new Profile;
$result = $request->Notification();
if(isset($result['isMessage']) && $result['isMessage'] == true)
{
return Redirect::back()->withMessage($result['message']);
}
else if (isset($result['isError']) && $result['isError'] == true)
{
return Redirect::back()->withErrors($result['error']);
}
}
Ideally speaking you should not create an object of Model in controller. You can just create the function as a static method inside model and call it from controller.