working on a restful api backend yii2 app, frontend is react. Two files: RBAMHelper.php and RoleHelper.php
RBAMHelper is role-based access control(manager) and RoleHelper is just user functions like userName(), userAgent(), userIp, userIdentity(), etc.
I want to try and use RBAMHelper with RoleHelper two functions isSupport() and isAdmin() and want to first check the RBAM:

is how the data is setup:

'admin.users' => [
	'admin1@example.com' => ['192.168.1.10', '203.0.113.50'],
	'admin2@example.com' => ['10.0.0.22'],
 ],

 'support.users' => [
 	'support1@example.com' => ['198.51.100.1'],
 	'support2@example.com' => ['198.51.100.2', '198.51.100.3'],
 ],

class RBAMHelper
{
	/**
	* Checks if an IP is in the list of allowed IPs, including support for CIDR notation.
	* @param string[] $allowedIps Array of allowed IP addresses or CIDR ranges.
	* @param string $ip IP address to check.
	* @return bool True if IP matches any allowed IP or subnet, false otherwise.
	*/
	protected static function ipInRangeArray(array $allowedIps, string $ip): bool
	{
		foreach ($allowedIps as $allowedIp)
		{
			if (self::ipMatches($ip, $allowedIp))
			{
				return true;
			}
		}
		
		return false;
	}
	
	/**
	* Determines whether a single IP matches an allowed IP or CIDR subnet.
	* @param string $ip IP address to check.
	* @param string $allowedIp IP address or subnet in CIDR notation.
	* @return bool True if $ip is within $allowedIp or equal to it.
	*/
	protected static function ipMatches(string $ip, string $allowedIp): bool
	{
		// If no CIDR mask given, treat as single IP
		if (strpos($allowedIp, '/') === false)
		{
			return filter_var($ip, FILTER_VALIDATE_IP) && $ip === $allowedIp;
		}
		
		// CIDR subnet check
		list($subnet, $mask) = explode('/', $allowedIp);
		
		// Invalid IP format
		if (!filter_var($ip, FILTER_VALIDATE_IP) || !filter_var($subnet, FILTER_VALIDATE_IP))
		{
			return false;
		}
		
		$ipLong = ip2long($ip);
		$subnetLong = ip2long($subnet);
		$maskLong = ~((1 << (32 - intval($mask))) - 1);
		
		return ($ipLong & $maskLong) === ($subnetLong & $maskLong);
	}
	
	/**
	* Checks if the given email belongs to an admin user and the IP is allowed.
	* @param string $email User email to check.
	* @param string|null $ip IP address of the user (optional but recommended).
	* @return bool True if user is an admin and IP is allowed.
	*/
	public static function isAdmin(string $email, ?string $ip = null): bool
	{
		//$adminUsers = \Yii::$app->params['adminUsers'] ?? [];
		$adminUsers = ParamHelper::get('admin.users', []);
		
		// If email not configured as admin user, fail fast
		if (!isset($adminUsers[$email]))
		{
			return false;
		}
		
		// Require IP for strict checking; reject if missing
		if ($ip === null)
		{
			return false;
		}
		
		$allowedIps = $adminUsers[$email];
		
		// Return true if IP matches any allowed IP or subnet
		return self::ipInRangeArray($allowedIps, $ip);
	}
	
	/**
	* Checks if the given email belongs to a support user and the IP is allowed.
	* @param string $email User email to check.
	* @param string|null $ip IP address of the user (optional but recommended).
	* @return bool True if user is support and IP is allowed.
	*/
	public static function isSupport(string $email, ?string $ip = null): bool
	{
		//$supportUsers = \Yii::$app->params['support.users'] ?? [];
		$supportUsers = ParamHelper::get('support.users', []);
		
		if (!isset($supportUsers[$email]))
		{
			return false;
		}
		
		if ($ip === null)
		{
			return false;
		}
		
		$allowedIps = $supportUsers[$email];
		
		return self::ipInRangeArray($allowedIps, $ip);
	}
	
class RoleHelper
{
	public static function userIp(): string|null
	{
		if (!\Yii::$app->has('request'))
		{
			return null;
		}
		
		return \Yii::$app->request->userIP;
	}
	
	public static function userAgent(): string|null
	{
		if (!\Yii::$app->has('request'))
		{
			return null;
		}
		
		$agent = \Yii::$app->request->userAgent;
		
		return (!empty($agent)) ? $agent : null;
	}
	
	public static function userIdentity(): IdentityInterface|null
	{
		if (self::isGuest())
		{
			return null;
		}
		
		$identity = \Yii::$app->user->identity;
		if ($identity instanceof IdentityInterface)
		{
			return $identity;
		}
		
		// Defensive fallback: If identity is not instance, treat as guest
		return null;
	}
	
	public static function userId(): int|null
	{
		$identity = self::userIdentity();
		if ($identity === null)
		{
			return null;
		}
		
		// Return the user ID as an integer.
		return (int) $identity->id;
	}
	
	public static function isAdmin(): bool
	{
		if (self::isGuest())
		{
			return false;
		}
		
		/**
		* Directly check the role assignment rather than permissions.
		* @url https://www.yiiframework.com/doc/api/2.0/yii-rbac-checkaccessinterface#checkAccess()-detail
		* @return bool
		*/
		return \Yii::$app->authManager->checkAccess(self::userId(), 'admin');
		
		/**
		* Check the role assignment via permissions.
		* @url https://www.yiiframework.com/doc/api/2.0/yii-web-user#can()-detail
		* @return bool
		*
		*	\Yii::$app->user->can('deleteUser');
		*
		$is = \Yii::$app->user->can('deleteUser') ? true : false;
		return (bool)$is;//*/
	}
	
	public static function isSupport(): bool
	{
		// same as isAdmin()
	}
}

watcha think?

im using them like this:

trait RbacHelperAccessTrait
{
	/**
	* Returns AccessControl behavior with integrated email+IP RBACHelper check for appAdmin role.
	* @param string[] $adminActions Actions to apply admin IP+email check to.
	* @return array Yii2 behavior config
	*/
	public function accessControlWithRbacHelper(array $actions = ['index']): array
	{
		return [
			/**
			* Access Control
			* @url https://www.yiiframework.com/doc/guide/2.0/en/structure-filters#access-control
			*
			* AccessControl provides simple access control based on a set of rules. In particular, before an action is executed,
			* AccessControl will examine the listed rules and find the first one that matches the current context variables such
			* as user IP address, user login status, etc.
			*
			*	The '@' symbol is used to indicate that a user must be logged in to access this action.
			*	The '?' symbol is used to say this action is available to anyone.
			*
			* Roles: userOwner, userAssist, appSupport, appAdmin
			*/
			'class' => AccessControl::class,
			'only' => $actions,
			'denyCallback' => function ($rule, $action)
			{
				throw new YiiForbiddenHttpException('Access denied.');// Customize message here
			},
			'rules' => [
				[
					'actions' => $actions,
					'allow' => false,
					'roles' => ['?'],// deny guests
				],[
					'actions' => $actions,
					'allow' => true,
					'roles' => ['appSupport'],// allow support role fully
				],[
					'actions' => $actions,
					'allow' => true,
					'roles' => ['appAdmin'],
					'matchCallback' => function ($rule, Action $action)
					{
						$user = \Yii::$app->user->identity;
						if (!$user)
						{
							return false;
						}
						
						$email = $user->email;
						$ip = \Yii::$app->request->userIP;
						
						return RBAMHelper::isAdmin($email, $ip);
					},
				],
			],
		];
	}
}