How to retrieve hidden property form a relationship model - laravel

i have 3 models: Order, Lancenter and ClientAccount
Lancenters can create Orders.
ClientAccounts stores username and password.
When an order is created, the Lancenter can choose an existant client account or create a new one, so i show up all ClientAccounts related with the current Lancenter.
For security reasons, i don't retrieve the ClientAccount password when a lancenter wants to create a new order.
So, in ClientAccount.php i have this:
protected $hidden = ['password'];
And in Lancenter.php:
public function client_accounts()
{
return $this->hasMany('App\ClientAccount', 'id_lancenter');
}
In LancenterController.php this function retrieves lancenter's client accounts without the password:
public function getClientAccounts()
{
$lancenter = Lancenter::with('client_accounts')->where('id_owner', Auth::id())->first();
return response()->json(['client_accounts' => $lancenter->client_accounts]);
}
The problem is that the created order belongs to a ClientAccount and in this case i need to retrieve also the password of ClientAccount.
So i have in Order.php:
public function client_account()
{
return $this->belongsTo('App\ClientAccount', 'id_client_account');
}
And this function in OrderController.php retrieves new orders:
$orders = Order::with('client_account')->where('status', $status)->get();
return response()->json(['orders' => $orders]);
Obviously, the ClientAccount is retrieved without the password.
I get it by doing a loop to get the ClientAccount of each order in the index function in OrderController, but i supose that there is a cleaner to do it. Hope you can help me.
Update:
this is the loop in OrderController that i'm talking about
public function index($status)
{
$orders = Order->where('status', $status)->get();
foreach($orders as $key => $order) {
$client_account = ClientAccount::find($order->id_client_account)->makeVisible('password')->toArray();
$orders[$key]['client_account'] = $client_account;
}
return response()->json(['orders' => $orders]);
}

Related

Restrict some users to update or view other users data in Laravel

I have users with role manager, and I only want them to update or view other users(employee) data that belong in the same department as the manager user. If the manager user is not in the same department as the user he's trying to update it should redirect the back.
i.e., the manager might try to change the user id in the URL, and I want to deny access to if that user belongs in another department.
I have all my roles and permissions set up.
The Department field is in USER TABLE
public function show($id)
{
$team = User::where('id', $id)->with('roles')->first();
return view('backend.user.team.show', compact('team'));
}
public function edit($id)
{
$user_roles = Role::all();
$team = User::find($id);
$business = Business::all();
return view('backend.user.team.edit', compact('team', 'user_roles', 'business'))->with('user', auth()->user());
}
You should use policies and gates.
Take a look at the documentation:
Writing policies
Writing gates
Basically, you should do something like this:
Create a policy to handle your user permissions:
php artisan make:policy UsersPolicy
This command will create a UsersPolicy file within the App/policies/ directory.
Open the UsersPolicy file and create a checkUserDepartament within that file:
public function checkUserDepartament(User $user, User $userToBeManaged)
{
return $user->departament === $userToBeManaged->departament;
}
The function above return true if the current logged in user departament is the same of the user you want to edit. Otherwise, return false.
Within your AuthServiceProvide:
Gate::define('user-belongs-to-same-departament', 'App\Policies\UsersPolicy#checkUserDepartament');
To use the Gate, do something like this within your controller:
use Gate; //At the top of the controller.
// I assume that $id is the id of the user you want to edit.
public function edit($id)
{
if(Gate::allows('user-belongs-to-same-departament', User::find($id))){
$user_roles = Role::all();
$team = User::find($id);
$business = Business::all();
return view('backend.user.team.edit', compact('team', 'user_roles', 'business'))->with('user', auth()->user());
}else {
return response('Unauthorized', 401);
}
}
Hope it helps.

check if collection contains id = (some id) where associated with a user id

I need to check if a collection of user submitted data contains an id of that data where the user that posted that data is the same user that is authenticated and performing the request.
How can I do this with the collection methods available in eloquent?
example:
public function index(){
$user_id = Auth::id();
if(Request::ajax()){
$suggested_data_id = Input::get('suggested_data_id');
$LatestSuggestions = Suggested_data::with('user')->latest()->orderBy('id', 'desc')->take(10)->get();
if($LatestSuggestions->contains('id', $suggested_data_id)->where( // the user that posted that data that is found in the collection is the authenticated user )){
return response()->json(array('latest_suggestions' => $LatestSuggestions));
}else{
$userLatestAddition = Suggested_data::with('user')->where('id', '=', $suggested_data_id)->get();
return response()->json(array('latest_suggestions' => $LatestSuggestions, 'last_user_addition' => $userLatestAddition));
}
}
}

How can i get codeigniter session database blob value?

With Codeigniter session.
I have created the ci_session table.
In this table I save session datas in the blob datatype.
$sess_data= array(
'logged_in' => TRUE
);
$this->session->set_userdata($sess_data);
For count all online users, I need to get logged_in==1 value in blob datatype.
For example, user 1 is logged in with Chrome web browser. User2 is logged in with Mozilla. In the database there are 2 sessions with the different session id.
How can i get this all logged_in==1 values in this ci_session table?
This is my model function.
Please help me the fill where place in this function?
public function count_online_users(){
$this->db->select('*');
$this->db->from('ci_session');
$this->db->where(...........);
$query = $this->db->get()->num_rows();
return $query;
}
Check this this method you have to follow
First you have to update logged_in = 1 in your users table as your defined name
after you get number of users are logged_in
// Update user in to call this function
$data = array(
'logged_in' => '1'
);
public function update_user($user_id, $data)
{
$this->db->where('id',$user_id);
$this->db->update('users',$data);
}
// After you get logged in user in total value
public function count_online_users()
{
$this->db->select('*');
$this->db->from('users');
$this->db->where('logged_in','1');
$query = $this->db->get()->num_rows();
return $query;
}
You can use javascript and asynchron request for update field. When you close the window, the handler of window.onunload is called
var unloadHandler = function(e){
//here ajax request to close session
};
window.unload = unloadHandler;
To solve the problem of redirection, php side you can use a counter
class someController extends Controller {
public function methodWithRedirection(){
$this->session->set_userdata('isRedirection', 1);
//here you can redirect
}
}
class homeController extends Controller{
public function closeConnection(){
$this->load->library('session');
if($this->session->userdata('isRedirection')!== 1){
//destroy session
}
}
}

Laravel profile edit

Alright , I have used this way to save the users info and It works perfect,
static public function memberSave($request) {
$signup = false;
$member = new Members();
$member->name = $request['name'];
$member->email = $request['email'];
$member->password = bcrypt($request['password']);
$member->save();
if (!empty($member->id)) {
$new_id = $member->id;
DB::insert("INSERT INTO roles VALUES ($new_id, 5613)");
$signup = true;
Session::flash('sm', 'Thank you! You have signed up successfully!');
}
return $signup;
}
but when making this for editing the profile(by user) It doesn't work
becuase I use new(); (making object)
I also didn't succeed to use find(); so I tried to use this
static public function saveProfile($id,$name,$email,$password) {
$sql = "UPDATE members SET name=?,email=?,password=? WHERE id=?";
$member = DB::select($sql, [$name,$email,$password,$id]);
but when I want to bcrypt the password in laravel doesnt work .
this is the code also in the second page
public function postProfile(ProfileValidation $request) {
if (Members::saveProfile($request['id'], $request['name'], $request['email'], $request['password'])) {
return redirect('');
}
}
I hope getting helped for editing the users profile by laravel , thanks.
Your Members class must extend Eloquent\Model for following this code to work.
class Members extends Model {
// optional
protected $table = 'members';
...
To find and update the member using email,
// find the single member
$member = Members::where('email', request['email'])->first();
// update the member
$member->name = $request['name'];
$member->password = $request['password'];
// now save the updated member
$member->save();
In order to to encrypt Password, Laravel provides Hash Facade,
// import this
use Hash;
...
// encrypt Password
$encrypted = Hash::make($request['password']);
...
if you want your user automatically hash the password at your model put:
public function setPasswordAttribute($value)
{
$this->attributes['password'] = Hash::make($value);
}
and you can directly check for the user if exist create new or update it:
public function saveMember($request)
{
$member = Member::findOrNew($request->email);
//All your input you want to save
$member->save();
}

Object Oriented Approach in Codeigniter Model

I have been wondering what is the right way to write code in OO style in model. Certainly you can have a function that retrieve data from DB and then map to model-level variables. This approach, however, becomes counterintuitive when you have other function in model trying to get other data from BD. For example:
class User extends CI_Model {
$id, $name, $age .... ;
public function get_user_from_db_with_id($id) {
...
// get data and map to variable.
}
public function get_all_users() {
// return all users in db
}
}
somewhere in controller:
$user = new User();
$ben = $user->get_user_from_db_with_id($id);
// this does not make sense!!
$all_user = $ben->get_all_users();
Any thought or comment?
Thanks in advance!
I had to make a similar decision and opted for this (trimmed for clarity)
class UserModel extends MY_Model
{
public $UserID = 0;
public $CustomerID = null;
public $FirstName = '';
public $LastName = '';
public $EmailAddress = '';
public $Password = null;
public $UserGroupID = true;
function __construct()
{
parent::__construct();
}
private function get($id)
{
$row = $this->get($id);
if ($row !== null)
{
$this->dbResultToObject($row, $this);
}
}
// Return an array of User objects
public function get_list($deleted = false, $userIDToInclude = null)
{
$params = array(null, $deleted, $userIDToInclude);
$query = $this->db->call("spUserGet", $params);
$users = array();
foreach ($query->result() as $row)
{
$user = new UserModel();
$this->dbResultToObject($row, $user);
$users[] = $user;
}
return $users;
}
// Other Methods (Validate, Save etc)
}
I use a mixture of public, protected and private properties so that the reflection code I've written to map the properties from the DB results and to the DB sproc calls then only includes the public properties and prevents too many parameters being sent. But that's getting off-topic so my controller then just looks like:
class Users extends MY_Controller
{
public function __construct()
{
parent::__construct();
$this->load->model('UserModel', 'user');
}
....
}
Then a list can be retrieved with
$users = $this->user->get_list();
And a single record with
$user = $this->user->get($userID);
i'm a big fan of thinking about the design in terms of "roles" - not resources. so a "User" is going to be able to get their own Profile. but its only going to be an "Admin" who is able to get All User Profiles.
so that distinction and important separation between what a User can do - get one record - and what an Admin can do - get all records - starts by having separate controllers for each. The User Controller methods are based upon verifying a single user and granting them access to one record. The Admin Controller methods are based upon verifying an admin and granting them access to all records. And this makes sense even from a URL design standpoint - you want your admin area clearly separate.
This separation at the controller makes everything simpler and easier. When you are resource oriented you are constantly checking the credentials in every method and even in your views. Views should be as simple as possible and not be tasked with "is this person an admin"? When you are role oriented - you check the credentials in the controller - and then your methods, the models, and the views are appropriate for what that 'role' needs to accomplish.
Since you are think about OO programming, i think you need to think: what does this class represent?
each instance means one user?
each instance means one user-data-generator?
if it's the first case, it makes sense this class has attributes like $id, $name, $age ....
and the following codes make sense
$user = new User();
$ben = $user->get_user_from_db_with_id($id);
if it's the second case, it shouldn't have the attributes like $id, $name, $age in you sample.
and these codes
$all_user = $ben->get_all_users();
should be replaced with this
$all_user = $user->get_all_users();

Resources