I'm trying to understand Gates, Permissions and Authentication better so I've created two Gates in my AuthServiceProvider. "isPermitted" checks if the user is permitted to access the given role and "isProjectRole" checks if the project given falls under the role the user is permitted to use.
My issue is that for some reason, the data passed to the isProjectRole Gate is incorrect, as it seems to be passing the User Facade instead of the project ID, which obviously comes back with the error that the User Facade can't be compared to an integer. But when I use DD to get the User, project ID and role ID it comes out as normal.
Using the DD inside of the controller
Using the DD inside the isProjectRole Gate
The routes are as follows:
Route::group(['middleware' => ['auth']], function () {
Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('welcome');
Route::get('/map/{role}/{project}', [App\Http\Controllers\MapController::class, 'index']);
});
Here's the code from my controller.
public function index(Request $request, $role, $project)
{
$user = Auth::user() ?? 'null';
// return dd('user: ' . $user->name . ' role: ' . $role . ' project: ' . $project);
if(Gate::denies('isProjectRole', $role, $project)){ // Project validation
return dd('You are not permitted to view this project.');
}
if(Gate::allows('isPermitted', $user->id, $role)){
....
Here's the code from the AuthServiceProvider.
public function boot()
{
$this->registerPolicies();
Gate::define('isPermitted', function($user, $role){
$userRole = DB::table('users')
->join('user_roles', 'users.id', '=', 'user_roles.user_id')
->join('roles', 'roles.id', '=', 'user_roles.role_id')
->select('roles.id')
->where('users.id', '=', $user->id)
->where('roles.id', '=', $role)
->first();
return $userRole ? true : false;
//return [$user, $role];
});
Gate::define('isProjectRole', function($roleId, $projectId){
// return dd($projectId, $roleId);
$projectIsInRole = DB::table('roles')
->join('role_projects', 'roles.id', '=', 'role_projects.role_id')
->join('projects', 'projects.id', '=', 'role_projects.project_id')
->select('projects.id')
->where('roles.id', '=', $roleId)
->where('projects.id', '=', $projectId)
->first();
return $projectIsInRole ? true : false;
});
}
Any help would be greatly appreciated. If I've left anything out that might help, please let me know.
Related
My Odoo user has access to two companies but when I run code like the following (using ripcord as described here) it only shows me data for the default company:
$domain = [];
$domain[] = ['year', '=', '2019'];
$fields = ['account_id', 'date', 'balance2'];
$groupby = ['account_id', 'date'];
$result = $models->execute_kw($a, $b, $c, 'account.budget.report', 'read_group', [$domain, $fields, $groupby], []);
Adding ['company_id', '=', '31'] to the array $domain doesn't work.
How can I change the company I currently want to work with?
Figured it out myself. Looking at how the browser changes the company I need to do this write operation first:
$result = $models->execute_kw($a, $b, $c, 'res.users', 'write', [[75], ['company_id' => 31]]);
75 is my user ID.
I want to show three tables, three tables are later to be exported, but I am having a problem here, please help me resolve my problem.
Thank you.
public function downloadExcel($type)
{
$data = DB::table('tb_siswa')
->join('tb_ayah', 'tb_siswa.id', '=', 'tb_ayah.id_siswa')
->join('tb_ibu', 'tb_siswa.id', '=', 'tb_ibu.id_siswa')
->select('tb_siswa.nm_lengkap', 'tb_ayah.nm_ayah', 'tb_ibu.nm_ibu')
->get();
return Excel::create('Data siswa', function($excel) use ($data) {
$excel->sheet('datasiswa', function($sheet) use ($data)
{
$sheet->fromArray($data);
});
})->download($type);
}
Add this line before return function
$data= json_decode( json_encode($data), true);
Hope it helps!
Im using a plugin for CakePHP to make the calls to obtain certain orders. I can call all orders with certain fields, but I was wondering how would I have to make the call to get the orders with a certain name or order_number? Here is the source for the call to Shopify. Its already authenticated and everything:
public function call($method, $path, $params=array())
{
if (!$this->isAuthorized())
return;
$password = $this->is_private_app ? $this->secret : md5($this->secret.$this->ShopifyAuth->token);
$baseurl = "https://{$this->api_key}:$password#{$this->ShopifyAuth->shop_domain}/";
$url = $baseurl.ltrim($path, '/');
$query = in_array($method, array('GET','DELETE')) ? $params : array();
$payload = in_array($method, array('POST','PUT')) ? stripslashes(json_encode($params)) : array();
$request_headers = in_array($method, array('POST','PUT')) ? array("Content-Type: application/json; charset=utf-8", 'Expect:') : array();
$request_headers[] = 'X-Shopify-Access-Token: ' . $this->ShopifyAuth->token;
list($response_body, $response_headers) = $this->Curl->HttpRequest($method, $url, $query, $payload, $request_headers);
$this->last_response_headers = $response_headers;
$response = json_decode($response_body, true);
if (isset($response['errors']) or ($this->last_response_headers['http_status_code'] >= 400))
throw new ShopifyApiException($method, $path, $params, $this->last_response_headers, $response);
return (is_array($response) and (count($response) > 0)) ? array_shift($response) : $response;
}
private function shopApiCallLimitParam($index)
{
if ($this->last_response_headers == null)
{
return 0;
}
$params = explode('/', $this->last_response_headers['http_x_shopify_shop_api_call_limit']);
return (int) $params[$index];
}
...and the code that makes the GET call:
// I only want the id and title of the collections
$fields = "fields=name,id,status,financial_status,fulfillment_status,billing_address,customer";
// get list of collections
$custom_collections = $this->ShopifyAPI->call('GET', "/admin/orders.json", $fields);
$this->set('collections', $custom_collections);
I think I'm missing the place where I can put the conditions for the call to get certain orders. I've already read the API documentation but can't seem to get the answer.
I've tried putting the ?name=%231001 on the url after .json to try and get the order #1001, but it brings back a empty array.
Then I tried ?order_number=1001 but it brings me every order with as well 1001 D: This is really confusing, Could anyone help me?
Thanks in advance.
Well I found out that you can actually get the order using the name or order_number. Its another property that is not listed on the documentation for some reason. But in the URL, if your using another language, all you have to add in the GET is admin/order.json?name=%2310001&status=any this is to get the order 10001 so just add the order_number after the %23. I saw this on a forum in Shopify university, I was just implementing this wrong on my code. If your using the CakePhp shopify plugin like me all I did was add on the $field the ?name=%23". number ."&status=any";
Ill leave the code here:
$this->layout = 'main';
$order_number = "18253";
$fields = "name=%23". $order_number ."&status=any";
$order = $this->ShopifyAPI->call('GET', "/admin/orders.json", $fields);
if (!empty($order)) {
$this->set('order', $order);
} else {
$this->Session->setFlash('<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button> No existe el numero de orden ingresado.','default',array('class' => 'alert alert-danger alert-dismissible', 'type' => 'alert'));
}
Hope this helps someone :P
I have email field in signup form ,
I want to validate email domain with database e.g
Email adress is : example#work.com or etc#etc.com
Now I want validate that work.com or etc.com is listed in db or not , if not then it should not be vaidate.!
Can Anyone help me with this ?
Code:
public function validate($attributes = null, $clearErrors = true) {
parent::validate($attributes, $clearErrors);
if (!$this->hasErrors('email')) {
$a = explode('#', $this->email);
if (isset($a[1])) {
$record = AllowedDomains::model()->findByAttributes(array('domain'=>$a[1]));
if ($record === null) {
$this->addError('email', "This domain isn't allowed");
}
}
}
return !$this->hasErrors();
}
Notes:
put this code in the model
email - the field holding the email address
AllowedDomains - the CActiveRecord of the table that holds the allowed domains
domain - replace with the correct database field
don't forget to add the e-mail validator in the rules() function. This will filter out invalid email addresses and the above code will not run if something's wrong
You could accomplish this by adding a custom yii validator in the rules section of your Model. Here is some example code:
public $email; // This is the field where the email is stored
/**
* #return array validation rules for model attributes.
*/
public function rules()
{
return array(
array('email', 'checkDomain'),
);
}
Afterwards, you can add the custom validation function
public function checkDomain($attribute,$params)
{
$sEmailDomain = substr(strrchr($this->email, "#"), 1);
// Check if the domain exists
...
// If the domain exists, add the error
$this->addError('email', 'Domain already exists in the database');
}
More information can be found here: http://www.yiiframework.com/wiki/168/create-your-own-validation-rule/
Is there a simple way of adding custom fields to a model? Say I have a table "user" with 3 fields: id, name and surname. I want this:
$user = User::model()->findByPk(1);
$echo $user->fullName; // echoes name and surname
Please note: I want this custom field to be added via sql, smth like
$c = new CDbCriteria();
$c->select = 'CONCAT("user".name, "user".surname) as fullName';
$user = User::model()->find($c);
Problem is that fullName property is not set.
UPD:
here is the code for a little bit trickier problem -- custom field from another table. This is how it's done:
$model = Application::model();
$model->getMetaData()->columns = array_merge($model->getMetaData()->columns, array('fullName' => 'CONCAT("u".name, "u".surname)'));
$c = new CDbCriteria();
$c->select = 'CONCAT("u".name, "u".surname) as fullName';
$c->join = ' left join "user" "u" on "t".responsible_manager_id = "u".id';
$model->getDbCriteria()->mergeWith($c);
foreach ($model->findAll() as $o) {
echo '<pre>';
print_r($o->fullName);
echo '</pre>';
}
You can add a function to the User class:
public function getFullName() { return $this->name.' '.$this->surname; }
This will return the full name as if it were an attribute from the database. This is much easier than adding a calculated column to the SQL.
In model
public function getMetaData(){
$data = parent::getMetaData();
$data->columns['fullName'] = array('name' => 'fullName');
return $data;
}
Thus not recommended