Jump to content

Denied Access Hook Based on Custom Field


HBDynamic

Recommended Posts

Hello!

I have a custom field we created for clients called "Sales Rep". We would like to know if it's possible to write a hook that when trying to view a client profile or tickets the system would check to see if the "Admin Role" is "Full Administrator" or "Development Dept (Full Admin)" or the admin name is what is in the "Sales Rep" field they would have access if not, it would deny access.

Thank you for your time.

Link to comment
Share on other sites

Yes it sound's possible. 

So it would be tricky as you would have to find every hook for the clients section and every hook for the support ticket section if there is one that is!

If I were doing it I would use https://developers.whmcs.com/hooks-reference/admin-area/#adminareapage as it runs on every admin page and then just check the URL to work out when to run the Auth code :) most likley by checking when ?userid= is set which is on each of the client pages the only problem with this is that they would see all of the tickets on the /admin/supporttickets.php page as you could only get the client ID on the support ticket page itself by SQL along the lines of GET clientID from tbltickets WHERE ticket id = ticket;

Here's all the Hooks: https://developers.whmcs.com/hooks-reference/

Once you figure out which hooks to use and can get the client ID variable you then need to make a SQL to grab the custom field or check if the custom field is available in the Hook Variables.

once that's done you could make that as advanced as you wanted so you could see all clients and tickets but specific salesRepAdmin groups can only see client information and tickets where the customField = salesRepAdmin,

This would however slow down your page load on the pages you set it to run on as it has to get the customfield of the client ID and then match it against the admin logged in to produce the result and if it were a ticket then 

Link to comment
Share on other sites

TomoTech, 

I want to thank you for taking time with this post. I looked all over and even asked WHMCs if they could help but understandably I was directed to this channel. I finally decided I would just buckle down and do it on my own as I knew it would not be hard just that I did not really have the time. But be that as it may. I wrote the following Hook. I am going to share this as I am sure it can be coded up better and if anyone has the insight and wishes to do so please do. I am also sure it can be optimized as I did not spend much time on it.  I also added to it a list of active tickets for a give client to make it eaiser to jump around. Once again, please excuse the curdeness as I have not yet had the time to clean up or document the hook as I normally would.

 

 

<?php
/**
 * Prevent Staff access to certian areas..
 *
 * @author     DynamicIDX
 * @copyright  Copyright (c) SENTQ 2018
 * @link       http://www.whmcms.com/
 */
 
if (!defined("WHMCS"))
   die("This file cannot be accessed directly");
   
use WHMCS\Session;
use WHMCS\Ticket\Watchers;
use Illuminate\Database\Capsule\Manager as Capsule;

function hook_verify_sales_agent($vars) {

	//Where the custom field name is: Sales Rep of type Drow Down with values of "Dynamic IDX,Nina Tewell,Roger Grant,Haley Blankenship,Kim Conger"
	//So the Check would not look if the admin had full rights. Other wise it would take the staff/admins full name and compare it to the field values.

	//Depending on the hook, we have to lookup the user id based on what we have.
	//Ticket id so look up the id from ticket.. 
	$fullAdmin = ['1','5','8','10'];
	$allowedSalesAgents = ['everyone','mls association'];

	
	$debug_out = '';
	$msg_out = '';
	$where_are_we = '';
	
	//foreach($vars as $k => $v)
	//{
	//	$debug_out.= '['.$k.'] = ('.$v.')<br>';
	//}
	
	$theurlpath = $_SERVER['REQUEST_URI'];
	$debug_out.=' Path('.$theurlpath.')   ';
	
	$adminUserID = Session::get('adminid');
	if ($adminUserID > 0)
		$debug_out.=' AdminID('.$adminUserID.')   ';
	else
	{
		return ;
	}
	
	//
	//This section needs to be cleaned up with a simple function call.. on my todo.
	//
	$the_action = $_GET['action'];
	$debug_out.=' page('.$the_action.')   ';
	if (strpos($theurlpath, 'affiliates') !== false)
	{
		$where_are_we = 'affiliates';
		$theAffID = $_GET['id'];
		$theUser = Capsule::table('tblaffiliates')->where('id', '=', $theAffID) ->value('clientid');
	}
	else if (isset($vars['userid']))
	{
  	$where_are_we = 'user';
		$theUser = $vars['userid'];
	}
	else if (isset($_GET['userid']))
	{
  	$where_are_we = 'user';
		$theUser = $_GET['userid'];
	}
	else if (isset($vars['ticketid']) || $the_action == 'viewticket' || $the_action == 'view')
  {
  	$where_are_we = 'ticket';

  	if ($the_action == 'viewticket' || $the_action == 'view')
  	{
  		$theTicket = $_GET['id'];
			$theUser = Capsule::table('tbltickets')->where('id', '=', $theTicket) ->value('userid');
  		
  	}
  	else
  	{
  		$theTicket = $vars['ticketid'];
			$theUser = Capsule::table('tbltickets')->where('tid', '=', $theTicket) ->value('userid');
		}
  	
	
		$debug_out .= ' TicketID: ['.$theTicket.'] Userid ['.$theUser.'] ';
		
		//If ticket does not have a userid, lets try to locate the name...
		if ($theUser == 0 || empty($theUser))
		{
			$theUserEmail = Capsule::table('tbltickets')->where('id', '=', $theTicket) ->value('email');
			$thecontactname = Capsule::table('tbltickets')->where('id', '=', $theTicket) ->value('name');
			$theUser = Capsule::table('tblcontacts')->where('email', '=', $theUserEmail) ->value('userid');
			$debug_out .= ' Ticket email ['.$theUserEmail.'] ';
			$msg_out .= $thecontactname.' is a sub account. <br/>';
		}
	}
	else if (isset($vars['id']) || $the_action == 'edit')
	{
  	$where_are_we = 'invoice';
  	
  	if ($the_action == 'edit')
			$theInvoice = $_GET['id'];
  	else
			$theInvoice = $vars['id'];
			
		$theUser = Capsule::table('tblinvoices')->where('id', '=', $theInvoice) ->value('userid');
	}
	else	
	{
  	$where_are_we = 'user';
		$theUser = $vars['userid'];
	}
		
  
	//Get custom field value from client..
	if ($theUser > 0 && !empty($theUser))
	{
	 	$fieldid = Capsule::table('tblcustomfields')->where('fieldname', '=', 'Sales Rep')->where('type', '=', 'client') ->value('id');
	 	$salesrepname = Capsule::table('tblcustomfieldsvalues')->where('fieldid', '=', "$fieldid")->where('relid', '=', $theUser)->value('value');
		$salesrepname_nocap = strtolower($salesrepname);
		$salesrepname_nocap = trim($salesrepname_nocap);

		//Get client name..and build a link to their profile..
		if ($where_are_we != 'user')
		{
	 	$client_firstname = Capsule::table('tblclients')->where('id', '=', $theUser)->value('firstname');
	 	$client_lastname = Capsule::table('tblclients')->where('id', '=', $theUser)->value('lastname');
	 	$client_name = $client_firstname.' '.$client_lastname;
	 	$client_link = "<strong><a target='_blank' href='clientssummary.php?userid=".$theUser."'>View ".$client_name."</a></strong>";
	 	
	 	$msg_out .='Click to view '.$client_link.'\'s account!<br/>';
		}
		
		$debug_out .= "UserID:[".$theUser."] FieldID:[".$fieldid."] SalesRep:[".$salesrepname."]<br/>";
	}
	else
	{
		$debug_out .= "[".$theUser."] Ticket not associated with any account";
	}


	//Get Admins information based on the id.
  
 	$admin_username = Capsule::table('tbladmins')->where('id', '=', $adminUserID)->value('username');
 	$admin_firstname = Capsule::table('tbladmins')->where('id', '=', $adminUserID)->value('firstname');
 	$admin_lastname = Capsule::table('tbladmins')->where('id', '=', $adminUserID)->value('lastname');
 	$admin_full_name = strtolower($admin_firstname).' '.strtolower($admin_lastname);
 	$admin_full_name = trim($admin_full_name);

	//First we have a few admin id's that we don't need to restrict anything so just ignore them.
	//We also have some demo clients that we want all our sales agents to see so we don't restrict those either.
	if (!in_array($adminUserID,$fullAdmin) && !in_array($salesrepname_nocap,$allowedSalesAgents))
	{
		//if not a full admin then see if the names match. If not then we know they are not allowed to view this clients info.
		if ($salesrepname_nocap == 	$admin_full_name)
		{
			$msg_out .= "This is your client!<br/>";
		}	
		else
		{
			$msg_out .= "Not your client!<br/>";
			header('Location: https://info.dynamicidx.com/admin/accessdenied.php'); //redirect the to home page for now.. Want to make this an access denied page..
		}
	}
	else
	{
		if ($theUser > 0)
			$msg_out .= "[".$salesrepname."]'s client<br/>";
		else
			$msg_out .= "Ticket not assiged to any client account<br/>";
		
   //echo "<br>Found Full Name [".$admin_full_name."]  Admin [".$adminUserID."] First name [".$admin_firstname."] Last name [".$admin_lastname."] Username [".$admin_username."]";
	}
	
	//if we are on the user profile we should show the active tickets..
	if ($where_are_we == 'user' || $where_are_we == 'ticket')
	{
		//They can view this client so lets show active tickets..
		//If viewing a ticket we will exclude the one we are looking at...
		if ($where_are_we != 'ticket' && $theUser> 0)
		{
			$tickets = Capsule::table('tbltickets')
		                   ->where('userid', $theUser)
		                   ->whereNotIn('status', ['Closed'])
		                   ->orderBy('date', 'desc')
		                   ->take(10)
		                   ->get();
    }
    else if ($theTicket > 0 && $theUser> 0)
    {
			$tickets = Capsule::table('tbltickets')
		                   ->where('userid', $theUser)
		                   ->whereNotIn('status', ['Closed'])
		                   ->where('id', '<>',$theTicket)
		                   ->orderBy('date', 'desc')
		                   ->take(10)
		                   ->get();
    }
		
		if (count($tickets)> 0)
		{

			$msg_out.='=============================================================';
			$msg_out.='<br/>[Top ['.count($tickets).'] Active Tickets for this client]';
			$msg_out.='<br/>=============================================================<br/>';
		
			foreach ($tickets as $ticket) {    
	  	     $msg_out .= '<p class="mytitleannoun"><i class="fa fa-file-text-o" aria-hidden="true" style="margin-right:15px;"></i><a style="margin-right:15px;" href="/admin/supporttickets.php?action=viewticket&id='.$ticket->id.'">('.$ticket->status.') '.$ticket->title.'</a><span> '.$ticket->department.'</span><font color="#b3b3b3"> '.fromMySQLDate($ticket->date).'</font></p>';
	   	}	
	  }
	}
 
	//Get staff's name trying to access page.

   //return $debug_out.'   '.$msg_out;
   return $msg_out;

}


add_hook("AdminAreaClientSummaryPage", 1, "hook_verify_sales_agent");
add_hook("AdminClientProfileTabFields", 1, "hook_verify_sales_agent");
add_hook("AdminClientServicesTabFields", 1, "hook_verify_sales_agent");
add_hook("AdminAreaViewTicketPage", 1, "hook_verify_sales_agent");
add_hook("ViewInvoiceDetailsPage", 1, "hook_verify_sales_agent");

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use & Guidelines and understand your posts will initially be pre-moderated